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/index.js CHANGED
@@ -1,11 +1,9 @@
1
1
  import * as __WEBPACK_EXTERNAL_MODULE_node_fs__ from "node:fs";
2
- import * as __WEBPACK_EXTERNAL_MODULE_semver__ from "semver";
2
+ import * as __WEBPACK_EXTERNAL_MODULE_node_os__ from "node:os";
3
+ import * as __WEBPACK_EXTERNAL_MODULE_node_path__ from "node:path";
3
4
  import * as __WEBPACK_EXTERNAL_MODULE_node_child_process__ from "node:child_process";
4
5
  import * as __WEBPACK_EXTERNAL_MODULE_node_util__ from "node:util";
5
- import * as __WEBPACK_EXTERNAL_MODULE_node_path__ from "node:path";
6
- import * as __WEBPACK_EXTERNAL_MODULE_os__ from "os";
7
- import * as __WEBPACK_EXTERNAL_MODULE_path__ from "path";
8
- import * as __WEBPACK_EXTERNAL_MODULE_fs__ from "fs";
6
+ import * as __WEBPACK_EXTERNAL_MODULE_semver__ from "semver";
9
7
  import * as __WEBPACK_EXTERNAL_MODULE_chalk__ from "chalk";
10
8
  var __webpack_modules__ = {
11
9
  "node:fs": function(module) {
@@ -22,6 +20,258 @@ function __webpack_require__(moduleId) {
22
20
  __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
23
21
  return module.exports;
24
22
  }
23
+ var external_node_fs_ = __webpack_require__("node:fs");
24
+ const agent_registry_home = (0, __WEBPACK_EXTERNAL_MODULE_node_os__.homedir)();
25
+ const agents = {
26
+ amp: {
27
+ name: 'amp',
28
+ displayName: 'Amp',
29
+ skillsDir: '.agents/skills',
30
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/agents/skills'),
31
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/amp'))
32
+ },
33
+ antigravity: {
34
+ name: 'antigravity',
35
+ displayName: 'Antigravity',
36
+ skillsDir: '.agent/skills',
37
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini/antigravity/skills'),
38
+ 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'))
39
+ },
40
+ 'claude-code': {
41
+ name: 'claude-code',
42
+ displayName: 'Claude Code',
43
+ skillsDir: '.claude/skills',
44
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.claude/skills'),
45
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.claude'))
46
+ },
47
+ clawdbot: {
48
+ name: 'clawdbot',
49
+ displayName: 'Clawdbot',
50
+ skillsDir: 'skills',
51
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.clawdbot/skills'),
52
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.clawdbot'))
53
+ },
54
+ codex: {
55
+ name: 'codex',
56
+ displayName: 'Codex',
57
+ skillsDir: '.codex/skills',
58
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codex/skills'),
59
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codex'))
60
+ },
61
+ cursor: {
62
+ name: 'cursor',
63
+ displayName: 'Cursor',
64
+ skillsDir: '.cursor/skills',
65
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.cursor/skills'),
66
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.cursor'))
67
+ },
68
+ droid: {
69
+ name: 'droid',
70
+ displayName: 'Droid',
71
+ skillsDir: '.factory/skills',
72
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.factory/skills'),
73
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.factory/skills'))
74
+ },
75
+ 'gemini-cli': {
76
+ name: 'gemini-cli',
77
+ displayName: 'Gemini CLI',
78
+ skillsDir: '.gemini/skills',
79
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini/skills'),
80
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.gemini'))
81
+ },
82
+ 'github-copilot': {
83
+ name: 'github-copilot',
84
+ displayName: 'GitHub Copilot',
85
+ skillsDir: '.github/skills',
86
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.copilot/skills'),
87
+ 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'))
88
+ },
89
+ goose: {
90
+ name: 'goose',
91
+ displayName: 'Goose',
92
+ skillsDir: '.goose/skills',
93
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/goose/skills'),
94
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/goose'))
95
+ },
96
+ kilo: {
97
+ name: 'kilo',
98
+ displayName: 'Kilo Code',
99
+ skillsDir: '.kilocode/skills',
100
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kilocode/skills'),
101
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kilocode'))
102
+ },
103
+ 'kiro-cli': {
104
+ name: 'kiro-cli',
105
+ displayName: 'Kiro CLI',
106
+ skillsDir: '.kiro/skills',
107
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kiro/skills'),
108
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.kiro'))
109
+ },
110
+ opencode: {
111
+ name: 'opencode',
112
+ displayName: 'OpenCode',
113
+ skillsDir: '.opencode/skills',
114
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.config/opencode/skills'),
115
+ 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'))
116
+ },
117
+ roo: {
118
+ name: 'roo',
119
+ displayName: 'Roo Code',
120
+ skillsDir: '.roo/skills',
121
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.roo/skills'),
122
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.roo'))
123
+ },
124
+ trae: {
125
+ name: 'trae',
126
+ displayName: 'Trae',
127
+ skillsDir: '.trae/skills',
128
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.trae/skills'),
129
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.trae'))
130
+ },
131
+ windsurf: {
132
+ name: 'windsurf',
133
+ displayName: 'Windsurf',
134
+ skillsDir: '.windsurf/skills',
135
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codeium/windsurf/skills'),
136
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.codeium/windsurf'))
137
+ },
138
+ neovate: {
139
+ name: 'neovate',
140
+ displayName: 'Neovate',
141
+ skillsDir: '.neovate/skills',
142
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.neovate/skills'),
143
+ detectInstalled: async ()=>(0, external_node_fs_.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(agent_registry_home, '.neovate'))
144
+ }
145
+ };
146
+ function getAllAgentTypes() {
147
+ return Object.keys(agents);
148
+ }
149
+ async function detectInstalledAgents() {
150
+ const installed = [];
151
+ for (const [type, config] of Object.entries(agents))if (await config.detectInstalled()) installed.push(type);
152
+ return installed;
153
+ }
154
+ function getAgentConfig(type) {
155
+ return agents[type];
156
+ }
157
+ function isValidAgentType(type) {
158
+ return type in agents;
159
+ }
160
+ function getAgentSkillsDir(type, options = {}) {
161
+ const config = agents[type];
162
+ if (options.global) return config.globalSkillsDir;
163
+ const cwd = options.cwd || process.cwd();
164
+ return (0, __WEBPACK_EXTERNAL_MODULE_node_path__.join)(cwd, config.skillsDir);
165
+ }
166
+ function exists(filePath) {
167
+ return external_node_fs_.existsSync(filePath);
168
+ }
169
+ function readJson(filePath) {
170
+ const content = external_node_fs_.readFileSync(filePath, 'utf-8');
171
+ return JSON.parse(content);
172
+ }
173
+ function writeJson(filePath, data, indent = 2) {
174
+ const dir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(filePath);
175
+ if (!exists(dir)) external_node_fs_.mkdirSync(dir, {
176
+ recursive: true
177
+ });
178
+ external_node_fs_.writeFileSync(filePath, `${JSON.stringify(data, null, indent)}\n`, 'utf-8');
179
+ }
180
+ function ensureDir(dirPath) {
181
+ if (!exists(dirPath)) external_node_fs_.mkdirSync(dirPath, {
182
+ recursive: true
183
+ });
184
+ }
185
+ function remove(targetPath) {
186
+ if (exists(targetPath)) external_node_fs_.rmSync(targetPath, {
187
+ recursive: true,
188
+ force: true
189
+ });
190
+ }
191
+ function copyDir(src, dest, options) {
192
+ const exclude = options?.exclude || [];
193
+ ensureDir(dest);
194
+ const entries = external_node_fs_.readdirSync(src, {
195
+ withFileTypes: true
196
+ });
197
+ for (const entry of entries){
198
+ if (exclude.includes(entry.name)) continue;
199
+ const srcPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(src, entry.name);
200
+ const destPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(dest, entry.name);
201
+ if (entry.isDirectory()) copyDir(srcPath, destPath, options);
202
+ else external_node_fs_.copyFileSync(srcPath, destPath);
203
+ }
204
+ }
205
+ function listDir(dirPath) {
206
+ if (!exists(dirPath)) return [];
207
+ return external_node_fs_.readdirSync(dirPath);
208
+ }
209
+ function isDirectory(targetPath) {
210
+ if (!exists(targetPath)) return false;
211
+ return external_node_fs_.statSync(targetPath).isDirectory();
212
+ }
213
+ function isSymlink(targetPath) {
214
+ if (!exists(targetPath)) return false;
215
+ return external_node_fs_.lstatSync(targetPath).isSymbolicLink();
216
+ }
217
+ function createSymlink(target, linkPath) {
218
+ const linkDir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath);
219
+ ensureDir(linkDir);
220
+ if (exists(linkPath)) remove(linkPath);
221
+ external_node_fs_.symlinkSync(target, linkPath, 'dir');
222
+ }
223
+ function getRealPath(linkPath) {
224
+ return external_node_fs_.realpathSync(linkPath);
225
+ }
226
+ function getSkillsJsonPath(projectRoot) {
227
+ const root = projectRoot || process.cwd();
228
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(root, 'skills.json');
229
+ }
230
+ function getSkillsLockPath(projectRoot) {
231
+ const root = projectRoot || process.cwd();
232
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(root, 'skills.lock');
233
+ }
234
+ function getCacheDir() {
235
+ const home = process.env.HOME || process.env.USERPROFILE || '';
236
+ return process.env.RESKILL_CACHE_DIR || __WEBPACK_EXTERNAL_MODULE_node_path__.join(home, '.reskill-cache');
237
+ }
238
+ function getHomeDir() {
239
+ return process.env.HOME || process.env.USERPROFILE || '';
240
+ }
241
+ function getGlobalSkillsDir() {
242
+ const home = getHomeDir();
243
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(home, '.claude', 'skills');
244
+ }
245
+ const AGENTS_DIR = '.agents';
246
+ const SKILLS_SUBDIR = 'skills';
247
+ function getCanonicalSkillsDir(options = {}) {
248
+ const { global: isGlobal = false, cwd } = options;
249
+ const baseDir = isGlobal ? getHomeDir() : cwd || process.cwd();
250
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, AGENTS_DIR, SKILLS_SUBDIR);
251
+ }
252
+ function getCanonicalSkillPath(skillName, options = {}) {
253
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(getCanonicalSkillsDir(options), skillName);
254
+ }
255
+ function shortenPath(fullPath, cwd) {
256
+ const home = getHomeDir();
257
+ const currentDir = cwd || process.cwd();
258
+ if (fullPath.startsWith(home)) return fullPath.replace(home, '~');
259
+ if (fullPath.startsWith(currentDir)) return `.${fullPath.slice(currentDir.length)}`;
260
+ return fullPath;
261
+ }
262
+ function isPathSafe(basePath, targetPath) {
263
+ const normalizedBase = __WEBPACK_EXTERNAL_MODULE_node_path__.normalize(__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(basePath));
264
+ const normalizedTarget = __WEBPACK_EXTERNAL_MODULE_node_path__.normalize(__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(targetPath));
265
+ return normalizedTarget.startsWith(normalizedBase + __WEBPACK_EXTERNAL_MODULE_node_path__.sep) || normalizedTarget === normalizedBase;
266
+ }
267
+ function sanitizeName(name) {
268
+ let sanitized = name.replace(/[/\\:\0]/g, '');
269
+ sanitized = sanitized.replace(/^[.\s]+|[.\s]+$/g, '');
270
+ sanitized = sanitized.replace(/^\.+/, '');
271
+ if (!sanitized || 0 === sanitized.length) sanitized = 'unnamed-skill';
272
+ if (sanitized.length > 255) sanitized = sanitized.substring(0, 255);
273
+ return sanitized;
274
+ }
25
275
  const execAsync = (0, __WEBPACK_EXTERNAL_MODULE_node_util__.promisify)(__WEBPACK_EXTERNAL_MODULE_node_child_process__.exec);
26
276
  class GitCloneError extends Error {
27
277
  repoUrl;
@@ -33,7 +283,7 @@ class GitCloneError extends Error {
33
283
  if (isAuthError) {
34
284
  message += '\n\nTip: For private repos, ensure git SSH keys or credentials are configured:';
35
285
  message += '\n - SSH: Check ~/.ssh/id_rsa or ~/.ssh/id_ed25519';
36
- message += '\n - HTTPS: Run \'git config --global credential.helper store\'';
286
+ message += "\n - HTTPS: Run 'git config --global credential.helper store'";
37
287
  message += '\n - Or use a personal access token in the URL';
38
288
  }
39
289
  super(message);
@@ -151,328 +401,46 @@ function buildRepoUrl(registry, ownerRepo) {
151
401
  gitlab: 'https://gitlab.com'
152
402
  };
153
403
  const baseUrl = registryUrls[registry] || `https://${registry}`;
154
- return `${baseUrl}/${ownerRepo}`;
155
- }
156
- function isGitUrl(source) {
157
- return source.startsWith('git@') || source.startsWith('git://') || source.startsWith('http://') || source.startsWith('https://') || source.endsWith('.git');
158
- }
159
- function parseGitUrl(url) {
160
- const cleanUrl = url.replace(/\.git$/, '');
161
- const sshMatch = cleanUrl.match(/^git@([^:]+):(.+)$/);
162
- if (sshMatch) {
163
- const [, host, path] = sshMatch;
164
- const parts = path.split('/');
165
- if (parts.length >= 2) {
166
- const owner = parts.slice(0, -1).join('/');
167
- const repo = parts[parts.length - 1];
168
- return {
169
- host,
170
- owner,
171
- repo,
172
- url,
173
- type: 'ssh'
174
- };
175
- }
176
- }
177
- const httpMatch = cleanUrl.match(/^(https?|git):\/\/([^/]+)\/(.+)$/);
178
- if (httpMatch) {
179
- const [, protocol, host, path] = httpMatch;
180
- const parts = path.split('/');
181
- if (parts.length >= 2) {
182
- const owner = parts.slice(0, -1).join('/');
183
- const repo = parts[parts.length - 1];
184
- return {
185
- host,
186
- owner,
187
- repo,
188
- url,
189
- type: 'git' === protocol ? 'git' : 'https'
190
- };
191
- }
192
- }
193
- return null;
194
- }
195
- class GitResolver {
196
- defaultRegistry;
197
- constructor(defaultRegistry = 'github'){
198
- this.defaultRegistry = defaultRegistry;
199
- }
200
- parseRef(ref) {
201
- const raw = ref;
202
- if (isGitUrl(ref)) return this.parseGitUrlRef(ref);
203
- let remaining = ref;
204
- let registry = this.defaultRegistry;
205
- let version;
206
- const registryMatch = remaining.match(/^([a-zA-Z0-9.-]+):(.+)$/);
207
- if (registryMatch) {
208
- registry = registryMatch[1];
209
- remaining = registryMatch[2];
210
- }
211
- const atIndex = remaining.lastIndexOf('@');
212
- if (atIndex > 0) {
213
- version = remaining.slice(atIndex + 1);
214
- remaining = remaining.slice(0, atIndex);
215
- }
216
- const parts = remaining.split('/');
217
- if (parts.length < 2) throw new Error(`Invalid skill reference: ${ref}. Expected format: owner/repo[@version]`);
218
- const owner = parts[0];
219
- const repo = parts[1];
220
- const subPath = parts.length > 2 ? parts.slice(2).join('/') : void 0;
221
- return {
222
- registry,
223
- owner,
224
- repo,
225
- subPath,
226
- version,
227
- raw
228
- };
229
- }
230
- parseGitUrlRef(ref) {
231
- const raw = ref;
232
- let gitUrl = ref;
233
- let version;
234
- let subPath;
235
- const gitSuffixIndex = ref.indexOf('.git');
236
- if (-1 !== gitSuffixIndex) {
237
- const afterGit = ref.slice(gitSuffixIndex + 4);
238
- if (afterGit) {
239
- const atIndex = afterGit.lastIndexOf('@');
240
- if (-1 !== atIndex) {
241
- version = afterGit.slice(atIndex + 1);
242
- const pathPart = afterGit.slice(0, atIndex);
243
- if (pathPart.startsWith('/')) subPath = pathPart.slice(1);
244
- } else if (afterGit.startsWith('/')) subPath = afterGit.slice(1);
245
- gitUrl = ref.slice(0, gitSuffixIndex + 4);
246
- }
247
- } else {
248
- const atIndex = ref.lastIndexOf('@');
249
- if (atIndex > 4) {
250
- version = ref.slice(atIndex + 1);
251
- gitUrl = ref.slice(0, atIndex);
252
- }
253
- }
254
- const parsed = parseGitUrl(gitUrl);
255
- if (!parsed) throw new Error(`Invalid Git URL: ${ref}. Expected format: git@host:owner/repo.git or https://host/owner/repo.git`);
256
- return {
257
- registry: parsed.host,
258
- owner: parsed.owner,
259
- repo: parsed.repo,
260
- subPath,
261
- version,
262
- raw,
263
- gitUrl
264
- };
265
- }
266
- parseVersion(versionSpec) {
267
- if (!versionSpec) return {
268
- type: 'branch',
269
- value: 'main',
270
- raw: ''
271
- };
272
- const raw = versionSpec;
273
- if ('latest' === versionSpec) return {
274
- type: 'latest',
275
- value: 'latest',
276
- raw
277
- };
278
- if (versionSpec.startsWith('branch:')) return {
279
- type: 'branch',
280
- value: versionSpec.slice(7),
281
- raw
282
- };
283
- if (versionSpec.startsWith('commit:')) return {
284
- type: 'commit',
285
- value: versionSpec.slice(7),
286
- raw
287
- };
288
- if (/^[\^~><]/.test(versionSpec)) return {
289
- type: 'range',
290
- value: versionSpec,
291
- raw
292
- };
293
- return {
294
- type: 'exact',
295
- value: versionSpec,
296
- raw
297
- };
298
- }
299
- buildRepoUrl(parsed) {
300
- if (parsed.gitUrl) return parsed.gitUrl;
301
- return buildRepoUrl(parsed.registry, `${parsed.owner}/${parsed.repo}`);
302
- }
303
- async resolveVersion(repoUrl, versionSpec) {
304
- switch(versionSpec.type){
305
- case 'exact':
306
- return {
307
- ref: versionSpec.value
308
- };
309
- case 'latest':
310
- {
311
- const latestTag = await getLatestTag(repoUrl);
312
- if (!latestTag) {
313
- const defaultBranch = await getDefaultBranch(repoUrl);
314
- return {
315
- ref: defaultBranch
316
- };
317
- }
318
- return {
319
- ref: latestTag.name,
320
- commit: latestTag.commit
321
- };
322
- }
323
- case 'range':
324
- {
325
- const tags = await getRemoteTags(repoUrl);
326
- const matchingTags = tags.filter((tag)=>{
327
- const version = tag.name.replace(/^v/, '');
328
- return __WEBPACK_EXTERNAL_MODULE_semver__.satisfies(version, versionSpec.value);
329
- });
330
- if (0 === matchingTags.length) throw new Error(`No version found matching ${versionSpec.raw} for ${repoUrl}`);
331
- matchingTags.sort((a, b)=>{
332
- const aVer = a.name.replace(/^v/, '');
333
- const bVer = b.name.replace(/^v/, '');
334
- return __WEBPACK_EXTERNAL_MODULE_semver__.compare(bVer, aVer);
335
- });
336
- return {
337
- ref: matchingTags[0].name,
338
- commit: matchingTags[0].commit
339
- };
340
- }
341
- case 'branch':
342
- return {
343
- ref: versionSpec.value
344
- };
345
- case 'commit':
346
- return {
347
- ref: versionSpec.value,
348
- commit: versionSpec.value
349
- };
350
- default:
351
- throw new Error(`Unknown version type: ${versionSpec.type}`);
352
- }
353
- }
354
- async resolve(ref) {
355
- const parsed = this.parseRef(ref);
356
- const repoUrl = this.buildRepoUrl(parsed);
357
- const versionSpec = this.parseVersion(parsed.version);
358
- const resolved = await this.resolveVersion(repoUrl, versionSpec);
359
- return {
360
- parsed,
361
- repoUrl,
362
- ref: resolved.ref,
363
- commit: resolved.commit
364
- };
365
- }
366
- }
367
- var external_node_fs_ = __webpack_require__("node:fs");
368
- function exists(filePath) {
369
- return external_node_fs_.existsSync(filePath);
370
- }
371
- function readJson(filePath) {
372
- const content = external_node_fs_.readFileSync(filePath, 'utf-8');
373
- return JSON.parse(content);
374
- }
375
- function writeJson(filePath, data, indent = 2) {
376
- const dir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(filePath);
377
- if (!exists(dir)) external_node_fs_.mkdirSync(dir, {
378
- recursive: true
379
- });
380
- external_node_fs_.writeFileSync(filePath, JSON.stringify(data, null, indent) + '\n', 'utf-8');
381
- }
382
- function ensureDir(dirPath) {
383
- if (!exists(dirPath)) external_node_fs_.mkdirSync(dirPath, {
384
- recursive: true
385
- });
386
- }
387
- function remove(targetPath) {
388
- if (exists(targetPath)) external_node_fs_.rmSync(targetPath, {
389
- recursive: true,
390
- force: true
391
- });
392
- }
393
- function copyDir(src, dest, options) {
394
- const exclude = options?.exclude || [];
395
- ensureDir(dest);
396
- const entries = external_node_fs_.readdirSync(src, {
397
- withFileTypes: true
398
- });
399
- for (const entry of entries){
400
- if (exclude.includes(entry.name)) continue;
401
- const srcPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(src, entry.name);
402
- const destPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(dest, entry.name);
403
- if (entry.isDirectory()) copyDir(srcPath, destPath, options);
404
- else external_node_fs_.copyFileSync(srcPath, destPath);
405
- }
406
- }
407
- function listDir(dirPath) {
408
- if (!exists(dirPath)) return [];
409
- return external_node_fs_.readdirSync(dirPath);
410
- }
411
- function isDirectory(targetPath) {
412
- if (!exists(targetPath)) return false;
413
- return external_node_fs_.statSync(targetPath).isDirectory();
414
- }
415
- function isSymlink(targetPath) {
416
- if (!exists(targetPath)) return false;
417
- return external_node_fs_.lstatSync(targetPath).isSymbolicLink();
418
- }
419
- function createSymlink(target, linkPath) {
420
- const linkDir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath);
421
- ensureDir(linkDir);
422
- if (exists(linkPath)) remove(linkPath);
423
- external_node_fs_.symlinkSync(target, linkPath, 'dir');
424
- }
425
- function getRealPath(linkPath) {
426
- return external_node_fs_.realpathSync(linkPath);
427
- }
428
- function getSkillsJsonPath(projectRoot) {
429
- const root = projectRoot || process.cwd();
430
- return __WEBPACK_EXTERNAL_MODULE_node_path__.join(root, 'skills.json');
431
- }
432
- function getSkillsLockPath(projectRoot) {
433
- const root = projectRoot || process.cwd();
434
- return __WEBPACK_EXTERNAL_MODULE_node_path__.join(root, 'skills.lock');
435
- }
436
- function getCacheDir() {
437
- const home = process.env.HOME || process.env.USERPROFILE || '';
438
- return process.env.RESKILL_CACHE_DIR || __WEBPACK_EXTERNAL_MODULE_node_path__.join(home, '.reskill-cache');
439
- }
440
- function getHomeDir() {
441
- return process.env.HOME || process.env.USERPROFILE || '';
442
- }
443
- function getGlobalSkillsDir() {
444
- const home = getHomeDir();
445
- return __WEBPACK_EXTERNAL_MODULE_node_path__.join(home, '.claude', 'skills');
446
- }
447
- const AGENTS_DIR = '.agents';
448
- const SKILLS_SUBDIR = 'skills';
449
- function getCanonicalSkillsDir(options = {}) {
450
- const { global: isGlobal = false, cwd } = options;
451
- const baseDir = isGlobal ? getHomeDir() : cwd || process.cwd();
452
- return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, AGENTS_DIR, SKILLS_SUBDIR);
453
- }
454
- function getCanonicalSkillPath(skillName, options = {}) {
455
- return __WEBPACK_EXTERNAL_MODULE_node_path__.join(getCanonicalSkillsDir(options), skillName);
456
- }
457
- function shortenPath(fullPath, cwd) {
458
- const home = getHomeDir();
459
- const currentDir = cwd || process.cwd();
460
- if (fullPath.startsWith(home)) return fullPath.replace(home, '~');
461
- if (fullPath.startsWith(currentDir)) return '.' + fullPath.slice(currentDir.length);
462
- return fullPath;
463
- }
464
- function isPathSafe(basePath, targetPath) {
465
- const normalizedBase = __WEBPACK_EXTERNAL_MODULE_node_path__.normalize(__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(basePath));
466
- const normalizedTarget = __WEBPACK_EXTERNAL_MODULE_node_path__.normalize(__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(targetPath));
467
- return normalizedTarget.startsWith(normalizedBase + __WEBPACK_EXTERNAL_MODULE_node_path__.sep) || normalizedTarget === normalizedBase;
404
+ return `${baseUrl}/${ownerRepo}`;
468
405
  }
469
- function sanitizeName(name) {
470
- let sanitized = name.replace(/[/\\:\0]/g, '');
471
- sanitized = sanitized.replace(/^[.\s]+|[.\s]+$/g, '');
472
- sanitized = sanitized.replace(/^\.+/, '');
473
- if (!sanitized || 0 === sanitized.length) sanitized = 'unnamed-skill';
474
- if (sanitized.length > 255) sanitized = sanitized.substring(0, 255);
475
- return sanitized;
406
+ function isGitUrl(source) {
407
+ return source.startsWith('git@') || source.startsWith('git://') || source.startsWith('http://') || source.startsWith('https://') || source.endsWith('.git');
408
+ }
409
+ function parseGitUrl(url) {
410
+ const cleanUrl = url.replace(/\.git$/, '');
411
+ const sshMatch = cleanUrl.match(/^git@([^:]+):(.+)$/);
412
+ if (sshMatch) {
413
+ const [, host, path] = sshMatch;
414
+ const parts = path.split('/');
415
+ if (parts.length >= 2) {
416
+ const owner = parts.slice(0, -1).join('/');
417
+ const repo = parts[parts.length - 1];
418
+ return {
419
+ host,
420
+ owner,
421
+ repo,
422
+ url,
423
+ type: 'ssh'
424
+ };
425
+ }
426
+ }
427
+ const httpMatch = cleanUrl.match(/^(https?|git):\/\/([^/]+)\/(.+)$/);
428
+ if (httpMatch) {
429
+ const [, protocol, host, path] = httpMatch;
430
+ const parts = path.split('/');
431
+ if (parts.length >= 2) {
432
+ const owner = parts.slice(0, -1).join('/');
433
+ const repo = parts[parts.length - 1];
434
+ return {
435
+ host,
436
+ owner,
437
+ repo,
438
+ url,
439
+ type: 'git' === protocol ? 'git' : 'https'
440
+ };
441
+ }
442
+ }
443
+ return null;
476
444
  }
477
445
  class CacheManager {
478
446
  cacheDir;
@@ -649,8 +617,8 @@ class ConfigLoader {
649
617
  getDefaults() {
650
618
  const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
651
619
  return {
652
- registry: config.defaults?.registry || DEFAULT_SKILLS_JSON.defaults.registry,
653
- installDir: config.defaults?.installDir || DEFAULT_SKILLS_JSON.defaults.installDir,
620
+ registry: config.defaults?.registry || 'github',
621
+ installDir: config.defaults?.installDir || '.skills',
654
622
  targetAgents: config.defaults?.targetAgents || [],
655
623
  installMode: config.defaults?.installMode || 'symlink'
656
624
  };
@@ -667,12 +635,12 @@ class ConfigLoader {
667
635
  }
668
636
  addSkill(name, ref) {
669
637
  if (!this.config) this.load();
670
- this.config.skills[name] = ref;
638
+ if (this.config) this.config.skills[name] = ref;
671
639
  this.save();
672
640
  }
673
641
  removeSkill(name) {
674
642
  if (!this.config) this.load();
675
- if (this.config.skills[name]) {
643
+ if (this.config?.skills[name]) {
676
644
  delete this.config.skills[name];
677
645
  this.save();
678
646
  return true;
@@ -685,7 +653,7 @@ class ConfigLoader {
685
653
  this.load();
686
654
  }
687
655
  return {
688
- ...this.config.skills
656
+ ...this.config?.skills
689
657
  };
690
658
  }
691
659
  hasSkill(name) {
@@ -697,247 +665,177 @@ class ConfigLoader {
697
665
  return skills[name];
698
666
  }
699
667
  }
700
- const LOCKFILE_VERSION = 1;
701
- class LockManager {
702
- projectRoot;
703
- lockPath;
704
- lockData = null;
705
- constructor(projectRoot){
706
- this.projectRoot = projectRoot || process.cwd();
707
- this.lockPath = getSkillsLockPath(this.projectRoot);
708
- }
709
- getLockPath() {
710
- return this.lockPath;
711
- }
712
- exists() {
713
- return exists(this.lockPath);
668
+ class GitResolver {
669
+ defaultRegistry;
670
+ constructor(defaultRegistry = 'github'){
671
+ this.defaultRegistry = defaultRegistry;
714
672
  }
715
- load() {
716
- if (this.lockData) return this.lockData;
717
- if (!this.exists()) {
718
- this.lockData = {
719
- lockfileVersion: LOCKFILE_VERSION,
720
- skills: {}
721
- };
722
- return this.lockData;
673
+ parseRef(ref) {
674
+ const raw = ref;
675
+ if (isGitUrl(ref)) return this.parseGitUrlRef(ref);
676
+ let remaining = ref;
677
+ let registry = this.defaultRegistry;
678
+ let version;
679
+ const registryMatch = remaining.match(/^([a-zA-Z0-9.-]+):(.+)$/);
680
+ if (registryMatch) {
681
+ registry = registryMatch[1];
682
+ remaining = registryMatch[2];
723
683
  }
724
- try {
725
- this.lockData = readJson(this.lockPath);
726
- return this.lockData;
727
- } catch (error) {
728
- throw new Error(`Failed to parse skills.lock: ${error.message}`);
684
+ const atIndex = remaining.lastIndexOf('@');
685
+ if (atIndex > 0) {
686
+ version = remaining.slice(atIndex + 1);
687
+ remaining = remaining.slice(0, atIndex);
729
688
  }
689
+ const parts = remaining.split('/');
690
+ if (parts.length < 2) throw new Error(`Invalid skill reference: ${ref}. Expected format: owner/repo[@version]`);
691
+ const owner = parts[0];
692
+ const repo = parts[1];
693
+ const subPath = parts.length > 2 ? parts.slice(2).join('/') : void 0;
694
+ return {
695
+ registry,
696
+ owner,
697
+ repo,
698
+ subPath,
699
+ version,
700
+ raw
701
+ };
730
702
  }
731
- reload() {
732
- this.lockData = null;
733
- return this.load();
734
- }
735
- save(lockToSave) {
736
- const toSave = lockToSave || this.lockData;
737
- if (!toSave) throw new Error('No lock to save');
738
- writeJson(this.lockPath, toSave);
739
- this.lockData = toSave;
740
- }
741
- get(name) {
742
- const lock = this.load();
743
- return lock.skills[name];
744
- }
745
- set(name, skill) {
746
- const lock = this.load();
747
- lock.skills[name] = skill;
748
- this.save();
749
- }
750
- remove(name) {
751
- const lock = this.load();
752
- if (lock.skills[name]) {
753
- delete lock.skills[name];
754
- this.save();
755
- return true;
703
+ parseGitUrlRef(ref) {
704
+ const raw = ref;
705
+ let gitUrl = ref;
706
+ let version;
707
+ let subPath;
708
+ const gitSuffixIndex = ref.indexOf('.git');
709
+ if (-1 !== gitSuffixIndex) {
710
+ const afterGit = ref.slice(gitSuffixIndex + 4);
711
+ if (afterGit) {
712
+ const atIndex = afterGit.lastIndexOf('@');
713
+ if (-1 !== atIndex) {
714
+ version = afterGit.slice(atIndex + 1);
715
+ const pathPart = afterGit.slice(0, atIndex);
716
+ if (pathPart.startsWith('/')) subPath = pathPart.slice(1);
717
+ } else if (afterGit.startsWith('/')) subPath = afterGit.slice(1);
718
+ gitUrl = ref.slice(0, gitSuffixIndex + 4);
719
+ }
720
+ } else {
721
+ const atIndex = ref.lastIndexOf('@');
722
+ if (atIndex > 4) {
723
+ version = ref.slice(atIndex + 1);
724
+ gitUrl = ref.slice(0, atIndex);
725
+ }
756
726
  }
757
- return false;
727
+ const parsed = parseGitUrl(gitUrl);
728
+ if (!parsed) throw new Error(`Invalid Git URL: ${ref}. Expected format: git@host:owner/repo.git or https://host/owner/repo.git`);
729
+ return {
730
+ registry: parsed.host,
731
+ owner: parsed.owner,
732
+ repo: parsed.repo,
733
+ subPath,
734
+ version,
735
+ raw,
736
+ gitUrl
737
+ };
758
738
  }
759
- lockSkill(name, options) {
760
- const lockedSkill = {
761
- source: options.source,
762
- version: options.version,
763
- resolved: options.resolved,
764
- commit: options.commit,
765
- installedAt: new Date().toISOString()
739
+ parseVersion(versionSpec) {
740
+ if (!versionSpec) return {
741
+ type: 'branch',
742
+ value: 'main',
743
+ raw: ''
766
744
  };
767
- this.set(name, lockedSkill);
768
- return lockedSkill;
745
+ const raw = versionSpec;
746
+ if ('latest' === versionSpec) return {
747
+ type: 'latest',
748
+ value: 'latest',
749
+ raw
750
+ };
751
+ if (versionSpec.startsWith('branch:')) return {
752
+ type: 'branch',
753
+ value: versionSpec.slice(7),
754
+ raw
755
+ };
756
+ if (versionSpec.startsWith('commit:')) return {
757
+ type: 'commit',
758
+ value: versionSpec.slice(7),
759
+ raw
760
+ };
761
+ if (/^[\^~><]/.test(versionSpec)) return {
762
+ type: 'range',
763
+ value: versionSpec,
764
+ raw
765
+ };
766
+ return {
767
+ type: 'exact',
768
+ value: versionSpec,
769
+ raw
770
+ };
771
+ }
772
+ buildRepoUrl(parsed) {
773
+ if (parsed.gitUrl) return parsed.gitUrl;
774
+ return buildRepoUrl(parsed.registry, `${parsed.owner}/${parsed.repo}`);
775
+ }
776
+ async resolveVersion(repoUrl, versionSpec) {
777
+ switch(versionSpec.type){
778
+ case 'exact':
779
+ return {
780
+ ref: versionSpec.value
781
+ };
782
+ case 'latest':
783
+ {
784
+ const latestTag = await getLatestTag(repoUrl);
785
+ if (!latestTag) {
786
+ const defaultBranch = await getDefaultBranch(repoUrl);
787
+ return {
788
+ ref: defaultBranch
789
+ };
790
+ }
791
+ return {
792
+ ref: latestTag.name,
793
+ commit: latestTag.commit
794
+ };
795
+ }
796
+ case 'range':
797
+ {
798
+ const tags = await getRemoteTags(repoUrl);
799
+ const matchingTags = tags.filter((tag)=>{
800
+ const version = tag.name.replace(/^v/, '');
801
+ return __WEBPACK_EXTERNAL_MODULE_semver__.satisfies(version, versionSpec.value);
802
+ });
803
+ if (0 === matchingTags.length) throw new Error(`No version found matching ${versionSpec.raw} for ${repoUrl}`);
804
+ matchingTags.sort((a, b)=>{
805
+ const aVer = a.name.replace(/^v/, '');
806
+ const bVer = b.name.replace(/^v/, '');
807
+ return __WEBPACK_EXTERNAL_MODULE_semver__.compare(bVer, aVer);
808
+ });
809
+ return {
810
+ ref: matchingTags[0].name,
811
+ commit: matchingTags[0].commit
812
+ };
813
+ }
814
+ case 'branch':
815
+ return {
816
+ ref: versionSpec.value
817
+ };
818
+ case 'commit':
819
+ return {
820
+ ref: versionSpec.value,
821
+ commit: versionSpec.value
822
+ };
823
+ default:
824
+ throw new Error(`Unknown version type: ${versionSpec.type}`);
825
+ }
769
826
  }
770
- getAll() {
771
- const lock = this.load();
827
+ async resolve(ref) {
828
+ const parsed = this.parseRef(ref);
829
+ const repoUrl = this.buildRepoUrl(parsed);
830
+ const versionSpec = this.parseVersion(parsed.version);
831
+ const resolved = await this.resolveVersion(repoUrl, versionSpec);
772
832
  return {
773
- ...lock.skills
774
- };
775
- }
776
- has(name) {
777
- const lock = this.load();
778
- return name in lock.skills;
779
- }
780
- isVersionMatch(name, version) {
781
- const locked = this.get(name);
782
- if (!locked) return false;
783
- return locked.version === version;
784
- }
785
- clear() {
786
- this.lockData = {
787
- lockfileVersion: LOCKFILE_VERSION,
788
- skills: {}
833
+ parsed,
834
+ repoUrl,
835
+ ref: resolved.ref,
836
+ commit: resolved.commit
789
837
  };
790
- this.save();
791
- }
792
- delete() {
793
- if (this.exists()) {
794
- const fs = __webpack_require__("node:fs");
795
- fs.unlinkSync(this.lockPath);
796
- }
797
- this.lockData = null;
798
- }
799
- }
800
- const agent_registry_home = (0, __WEBPACK_EXTERNAL_MODULE_os__.homedir)();
801
- const agents = {
802
- amp: {
803
- name: 'amp',
804
- displayName: 'Amp',
805
- skillsDir: '.agents/skills',
806
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/agents/skills'),
807
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/amp'))
808
- },
809
- antigravity: {
810
- name: 'antigravity',
811
- displayName: 'Antigravity',
812
- skillsDir: '.agent/skills',
813
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/antigravity/skills'),
814
- 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'))
815
- },
816
- 'claude-code': {
817
- name: 'claude-code',
818
- displayName: 'Claude Code',
819
- skillsDir: '.claude/skills',
820
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude/skills'),
821
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude'))
822
- },
823
- clawdbot: {
824
- name: 'clawdbot',
825
- displayName: 'Clawdbot',
826
- skillsDir: 'skills',
827
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.clawdbot/skills'),
828
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.clawdbot'))
829
- },
830
- codex: {
831
- name: 'codex',
832
- displayName: 'Codex',
833
- skillsDir: '.codex/skills',
834
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codex/skills'),
835
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codex'))
836
- },
837
- cursor: {
838
- name: 'cursor',
839
- displayName: 'Cursor',
840
- skillsDir: '.cursor/skills',
841
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.cursor/skills'),
842
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.cursor'))
843
- },
844
- droid: {
845
- name: 'droid',
846
- displayName: 'Droid',
847
- skillsDir: '.factory/skills',
848
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.factory/skills'),
849
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.factory/skills'))
850
- },
851
- 'gemini-cli': {
852
- name: 'gemini-cli',
853
- displayName: 'Gemini CLI',
854
- skillsDir: '.gemini/skills',
855
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/skills'),
856
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini'))
857
- },
858
- 'github-copilot': {
859
- name: 'github-copilot',
860
- displayName: 'GitHub Copilot',
861
- skillsDir: '.github/skills',
862
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.copilot/skills'),
863
- 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'))
864
- },
865
- goose: {
866
- name: 'goose',
867
- displayName: 'Goose',
868
- skillsDir: '.goose/skills',
869
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/goose/skills'),
870
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/goose'))
871
- },
872
- kilo: {
873
- name: 'kilo',
874
- displayName: 'Kilo Code',
875
- skillsDir: '.kilocode/skills',
876
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kilocode/skills'),
877
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kilocode'))
878
- },
879
- 'kiro-cli': {
880
- name: 'kiro-cli',
881
- displayName: 'Kiro CLI',
882
- skillsDir: '.kiro/skills',
883
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kiro/skills'),
884
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kiro'))
885
- },
886
- opencode: {
887
- name: 'opencode',
888
- displayName: 'OpenCode',
889
- skillsDir: '.opencode/skills',
890
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/opencode/skills'),
891
- 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'))
892
- },
893
- roo: {
894
- name: 'roo',
895
- displayName: 'Roo Code',
896
- skillsDir: '.roo/skills',
897
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.roo/skills'),
898
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.roo'))
899
- },
900
- trae: {
901
- name: 'trae',
902
- displayName: 'Trae',
903
- skillsDir: '.trae/skills',
904
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.trae/skills'),
905
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.trae'))
906
- },
907
- windsurf: {
908
- name: 'windsurf',
909
- displayName: 'Windsurf',
910
- skillsDir: '.windsurf/skills',
911
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codeium/windsurf/skills'),
912
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codeium/windsurf'))
913
- },
914
- neovate: {
915
- name: 'neovate',
916
- displayName: 'Neovate',
917
- skillsDir: '.neovate/skills',
918
- globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.neovate/skills'),
919
- detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.neovate'))
920
838
  }
921
- };
922
- function getAllAgentTypes() {
923
- return Object.keys(agents);
924
- }
925
- async function detectInstalledAgents() {
926
- const installed = [];
927
- for (const [type, config] of Object.entries(agents))if (await config.detectInstalled()) installed.push(type);
928
- return installed;
929
- }
930
- function getAgentConfig(type) {
931
- return agents[type];
932
- }
933
- function isValidAgentType(type) {
934
- return type in agents;
935
- }
936
- function getAgentSkillsDir(type, options = {}) {
937
- const config = agents[type];
938
- if (options.global) return config.globalSkillsDir;
939
- const cwd = options.cwd || process.cwd();
940
- return (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(cwd, config.skillsDir);
941
839
  }
942
840
  const installer_AGENTS_DIR = '.agents';
943
841
  const installer_SKILLS_SUBDIR = 'skills';
@@ -955,7 +853,7 @@ function installer_isPathSafe(basePath, targetPath) {
955
853
  return normalizedTarget.startsWith(normalizedBase + __WEBPACK_EXTERNAL_MODULE_node_path__.sep) || normalizedTarget === normalizedBase;
956
854
  }
957
855
  function installer_getCanonicalSkillsDir(isGlobal, cwd) {
958
- const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_os__.homedir)() : cwd || process.cwd();
856
+ const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_node_os__.homedir)() : cwd || process.cwd();
959
857
  return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, installer_AGENTS_DIR, installer_SKILLS_SUBDIR);
960
858
  }
961
859
  function installer_ensureDir(dirPath) {
@@ -1009,7 +907,7 @@ async function installer_createSymlink(target, linkPath) {
1009
907
  const linkDir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath);
1010
908
  installer_ensureDir(linkDir);
1011
909
  const relativePath = __WEBPACK_EXTERNAL_MODULE_node_path__.relative(linkDir, target);
1012
- const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_os__.platform)() ? 'junction' : void 0;
910
+ const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_node_os__.platform)() ? 'junction' : void 0;
1013
911
  external_node_fs_.symlinkSync(relativePath, linkPath, symlinkType);
1014
912
  return true;
1015
913
  } catch {
@@ -1132,6 +1030,106 @@ class Installer {
1132
1030
  }).filter((entry)=>entry.isDirectory() || entry.isSymbolicLink()).map((entry)=>entry.name);
1133
1031
  }
1134
1032
  }
1033
+ const LOCKFILE_VERSION = 1;
1034
+ class LockManager {
1035
+ projectRoot;
1036
+ lockPath;
1037
+ lockData = null;
1038
+ constructor(projectRoot){
1039
+ this.projectRoot = projectRoot || process.cwd();
1040
+ this.lockPath = getSkillsLockPath(this.projectRoot);
1041
+ }
1042
+ getLockPath() {
1043
+ return this.lockPath;
1044
+ }
1045
+ exists() {
1046
+ return exists(this.lockPath);
1047
+ }
1048
+ load() {
1049
+ if (this.lockData) return this.lockData;
1050
+ if (!this.exists()) {
1051
+ this.lockData = {
1052
+ lockfileVersion: LOCKFILE_VERSION,
1053
+ skills: {}
1054
+ };
1055
+ return this.lockData;
1056
+ }
1057
+ try {
1058
+ this.lockData = readJson(this.lockPath);
1059
+ return this.lockData;
1060
+ } catch (error) {
1061
+ throw new Error(`Failed to parse skills.lock: ${error.message}`);
1062
+ }
1063
+ }
1064
+ reload() {
1065
+ this.lockData = null;
1066
+ return this.load();
1067
+ }
1068
+ save(lockToSave) {
1069
+ const toSave = lockToSave || this.lockData;
1070
+ if (!toSave) throw new Error('No lock to save');
1071
+ writeJson(this.lockPath, toSave);
1072
+ this.lockData = toSave;
1073
+ }
1074
+ get(name) {
1075
+ const lock = this.load();
1076
+ return lock.skills[name];
1077
+ }
1078
+ set(name, skill) {
1079
+ const lock = this.load();
1080
+ lock.skills[name] = skill;
1081
+ this.save();
1082
+ }
1083
+ remove(name) {
1084
+ const lock = this.load();
1085
+ if (lock.skills[name]) {
1086
+ delete lock.skills[name];
1087
+ this.save();
1088
+ return true;
1089
+ }
1090
+ return false;
1091
+ }
1092
+ lockSkill(name, options) {
1093
+ const lockedSkill = {
1094
+ source: options.source,
1095
+ version: options.version,
1096
+ resolved: options.resolved,
1097
+ commit: options.commit,
1098
+ installedAt: new Date().toISOString()
1099
+ };
1100
+ this.set(name, lockedSkill);
1101
+ return lockedSkill;
1102
+ }
1103
+ getAll() {
1104
+ const lock = this.load();
1105
+ return {
1106
+ ...lock.skills
1107
+ };
1108
+ }
1109
+ has(name) {
1110
+ const lock = this.load();
1111
+ return name in lock.skills;
1112
+ }
1113
+ isVersionMatch(name, version) {
1114
+ const locked = this.get(name);
1115
+ if (!locked) return false;
1116
+ return locked.version === version;
1117
+ }
1118
+ clear() {
1119
+ this.lockData = {
1120
+ lockfileVersion: LOCKFILE_VERSION,
1121
+ skills: {}
1122
+ };
1123
+ this.save();
1124
+ }
1125
+ delete() {
1126
+ if (this.exists()) {
1127
+ const fs = __webpack_require__("node:fs");
1128
+ fs.unlinkSync(this.lockPath);
1129
+ }
1130
+ this.lockData = null;
1131
+ }
1132
+ }
1135
1133
  const logger = {
1136
1134
  info (message) {
1137
1135
  console.log(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].blue('ℹ'), message);
@@ -1199,8 +1197,17 @@ class SkillManager {
1199
1197
  if (this.isGlobal) return getGlobalSkillsDir();
1200
1198
  return this.config.getInstallDir();
1201
1199
  }
1200
+ getCanonicalSkillsDir() {
1201
+ const home = process.env.HOME || process.env.USERPROFILE || '';
1202
+ const baseDir = this.isGlobal ? home : this.projectRoot;
1203
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, '.agents', 'skills');
1204
+ }
1202
1205
  getSkillPath(name) {
1203
- return __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1206
+ const canonicalPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getCanonicalSkillsDir(), name);
1207
+ if (exists(canonicalPath)) return canonicalPath;
1208
+ const legacyPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1209
+ if (exists(legacyPath)) return legacyPath;
1210
+ return canonicalPath;
1204
1211
  }
1205
1212
  async install(ref, options = {}) {
1206
1213
  const { force = false, save = true } = options;
@@ -1213,11 +1220,13 @@ class SkillManager {
1213
1220
  const locked = this.lockManager.get(skillName);
1214
1221
  if (locked && locked.version === version) {
1215
1222
  logger.info(`${skillName}@${version} is already installed`);
1216
- return this.getInstalledSkill(skillName);
1223
+ const installed = this.getInstalledSkill(skillName);
1224
+ if (installed) return installed;
1217
1225
  }
1218
1226
  if (!force) {
1219
1227
  logger.warn(`${skillName} is already installed. Use --force to reinstall.`);
1220
- return this.getInstalledSkill(skillName);
1228
+ const installed = this.getInstalledSkill(skillName);
1229
+ if (installed) return installed;
1221
1230
  }
1222
1231
  }
1223
1232
  logger["package"](`Installing ${skillName}@${version}...`);
@@ -1231,7 +1240,7 @@ class SkillManager {
1231
1240
  if (exists(skillPath)) remove(skillPath);
1232
1241
  await this.cache.copyTo(parsed, version, skillPath);
1233
1242
  if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
1234
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`,
1243
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
1235
1244
  version,
1236
1245
  resolved: repoUrl,
1237
1246
  commit: cacheResult.commit
@@ -1239,7 +1248,9 @@ class SkillManager {
1239
1248
  if (!this.isGlobal && save && this.config.exists()) this.config.addSkill(skillName, ref);
1240
1249
  const locationHint = this.isGlobal ? '(global)' : '';
1241
1250
  logger.success(`Installed ${skillName}@${version} to ${skillPath} ${locationHint}`.trim());
1242
- return this.getInstalledSkill(skillName);
1251
+ const installed = this.getInstalledSkill(skillName);
1252
+ if (!installed) throw new Error(`Failed to get installed skill info for ${skillName}`);
1253
+ return installed;
1243
1254
  }
1244
1255
  async installAll(options = {}) {
1245
1256
  const skills = this.config.getSkills();
@@ -1306,7 +1317,7 @@ class SkillManager {
1306
1317
  skillName = name || skillJson.name || skillName;
1307
1318
  } catch {}
1308
1319
  const linkPath = this.getSkillPath(skillName);
1309
- ensureDir(this.getInstallDir());
1320
+ ensureDir(__WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath));
1310
1321
  createSymlink(absolutePath, linkPath);
1311
1322
  logger.success(`Linked ${skillName} → ${absolutePath}`);
1312
1323
  return {
@@ -1332,20 +1343,36 @@ class SkillManager {
1332
1343
  return true;
1333
1344
  }
1334
1345
  list() {
1335
- const installDir = this.getInstallDir();
1336
- if (!exists(installDir)) return [];
1337
1346
  const skills = [];
1338
- const dirs = listDir(installDir);
1339
- for (const name of dirs){
1340
- const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(installDir, name);
1347
+ const seenNames = new Set();
1348
+ const canonicalDir = this.getCanonicalSkillsDir();
1349
+ if (exists(canonicalDir)) for (const name of listDir(canonicalDir)){
1350
+ const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalDir, name);
1351
+ if (!isDirectory(skillPath)) continue;
1352
+ const skill = this.getInstalledSkillFromPath(name, skillPath);
1353
+ if (skill) {
1354
+ skills.push(skill);
1355
+ seenNames.add(name);
1356
+ }
1357
+ }
1358
+ const legacyDir = this.getInstallDir();
1359
+ if (exists(legacyDir) && legacyDir !== canonicalDir) for (const name of listDir(legacyDir)){
1360
+ if (seenNames.has(name)) continue;
1361
+ const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(legacyDir, name);
1341
1362
  if (!isDirectory(skillPath)) continue;
1342
- const skill = this.getInstalledSkill(name);
1343
- if (skill) skills.push(skill);
1363
+ if (isSymlink(skillPath)) try {
1364
+ const realPath = getRealPath(skillPath);
1365
+ if (realPath.includes(__WEBPACK_EXTERNAL_MODULE_node_path__.join('.agents', 'skills'))) continue;
1366
+ } catch {}
1367
+ const skill = this.getInstalledSkillFromPath(name, skillPath);
1368
+ if (skill) {
1369
+ skills.push(skill);
1370
+ seenNames.add(name);
1371
+ }
1344
1372
  }
1345
1373
  return skills;
1346
1374
  }
1347
- getInstalledSkill(name) {
1348
- const skillPath = this.getSkillPath(name);
1375
+ getInstalledSkillFromPath(name, skillPath) {
1349
1376
  if (!exists(skillPath)) return null;
1350
1377
  const isLinked = isSymlink(skillPath);
1351
1378
  const locked = this.lockManager.get(name);
@@ -1363,6 +1390,13 @@ class SkillManager {
1363
1390
  isLinked
1364
1391
  };
1365
1392
  }
1393
+ getInstalledSkill(name) {
1394
+ const canonicalPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getCanonicalSkillsDir(), name);
1395
+ if (exists(canonicalPath)) return this.getInstalledSkillFromPath(name, canonicalPath);
1396
+ const legacyPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1397
+ if (exists(legacyPath)) return this.getInstalledSkillFromPath(name, legacyPath);
1398
+ return null;
1399
+ }
1366
1400
  getInfo(name) {
1367
1401
  return {
1368
1402
  installed: this.getInstalledSkill(name),
@@ -1424,7 +1458,7 @@ class SkillManager {
1424
1458
  mode: mode
1425
1459
  });
1426
1460
  if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
1427
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`,
1461
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
1428
1462
  version,
1429
1463
  resolved: repoUrl,
1430
1464
  commit: cacheResult.commit
@@ -1438,7 +1472,7 @@ class SkillManager {
1438
1472
  name: skillName,
1439
1473
  path: sourcePath,
1440
1474
  version,
1441
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`
1475
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`
1442
1476
  };
1443
1477
  return {
1444
1478
  skill,