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/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,25 +20,289 @@ 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;
28
278
  originalError;
29
279
  isAuthError;
280
+ urlType;
30
281
  constructor(repoUrl, originalError){
31
282
  const isAuthError = GitCloneError.isAuthenticationError(originalError.message);
283
+ const urlType = GitCloneError.detectUrlType(repoUrl);
32
284
  let message = `Failed to clone repository: ${repoUrl}`;
33
285
  if (isAuthError) {
34
- message += '\n\nTip: For private repos, ensure git SSH keys or credentials are configured:';
35
- message += '\n - SSH: Check ~/.ssh/id_rsa or ~/.ssh/id_ed25519';
36
- message += '\n - HTTPS: Run \'git config --global credential.helper store\'';
37
- message += '\n - Or use a personal access token in the URL';
286
+ message += '\n\nTip: For private repos, ensure git credentials are configured:';
287
+ if ('ssh' === urlType) {
288
+ message += '\n - Check ~/.ssh/id_rsa or ~/.ssh/id_ed25519';
289
+ message += '\n - Ensure SSH key is added to your Git hosting service';
290
+ } else {
291
+ message += "\n - Run 'git config --global credential.helper store'";
292
+ message += '\n - Or use a personal access token in the URL';
293
+ }
38
294
  }
39
295
  super(message);
40
296
  this.name = 'GitCloneError';
41
297
  this.repoUrl = repoUrl;
42
298
  this.originalError = originalError;
43
299
  this.isAuthError = isAuthError;
300
+ this.urlType = urlType;
301
+ }
302
+ static detectUrlType(url) {
303
+ if (url.startsWith('git@') || url.startsWith('ssh://')) return 'ssh';
304
+ if (url.startsWith('http://') || url.startsWith('https://')) return 'https';
305
+ return 'unknown';
44
306
  }
45
307
  static isAuthenticationError(message) {
46
308
  const authPatterns = [
@@ -156,323 +418,41 @@ function buildRepoUrl(registry, ownerRepo) {
156
418
  function isGitUrl(source) {
157
419
  return source.startsWith('git@') || source.startsWith('git://') || source.startsWith('http://') || source.startsWith('https://') || source.endsWith('.git');
158
420
  }
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;
468
- }
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;
421
+ function parseGitUrl(url) {
422
+ const cleanUrl = url.replace(/\.git$/, '');
423
+ const sshMatch = cleanUrl.match(/^git@([^:]+):(.+)$/);
424
+ if (sshMatch) {
425
+ const [, host, path] = sshMatch;
426
+ const parts = path.split('/');
427
+ if (parts.length >= 2) {
428
+ const owner = parts.slice(0, -1).join('/');
429
+ const repo = parts[parts.length - 1];
430
+ return {
431
+ host,
432
+ owner,
433
+ repo,
434
+ url,
435
+ type: 'ssh'
436
+ };
437
+ }
438
+ }
439
+ const httpMatch = cleanUrl.match(/^(https?|git):\/\/([^/]+)\/(.+)$/);
440
+ if (httpMatch) {
441
+ const [, protocol, host, path] = httpMatch;
442
+ const parts = path.split('/');
443
+ if (parts.length >= 2) {
444
+ const owner = parts.slice(0, -1).join('/');
445
+ const repo = parts[parts.length - 1];
446
+ return {
447
+ host,
448
+ owner,
449
+ repo,
450
+ url,
451
+ type: 'git' === protocol ? 'git' : 'https'
452
+ };
453
+ }
454
+ }
455
+ return null;
476
456
  }
477
457
  class CacheManager {
478
458
  cacheDir;
@@ -633,6 +613,11 @@ class ConfigLoader {
633
613
  writeJson(this.configPath, toSave);
634
614
  this.config = toSave;
635
615
  }
616
+ ensureExists() {
617
+ if (this.exists()) return false;
618
+ this.create();
619
+ return true;
620
+ }
636
621
  create(options) {
637
622
  const config = {
638
623
  ...DEFAULT_SKILLS_JSON,
@@ -649,8 +634,8 @@ class ConfigLoader {
649
634
  getDefaults() {
650
635
  const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
651
636
  return {
652
- registry: config.defaults?.registry || DEFAULT_SKILLS_JSON.defaults.registry,
653
- installDir: config.defaults?.installDir || DEFAULT_SKILLS_JSON.defaults.installDir,
637
+ registry: config.defaults?.registry || 'github',
638
+ installDir: config.defaults?.installDir || '.skills',
654
639
  targetAgents: config.defaults?.targetAgents || [],
655
640
  installMode: config.defaults?.installMode || 'symlink'
656
641
  };
@@ -667,12 +652,12 @@ class ConfigLoader {
667
652
  }
668
653
  addSkill(name, ref) {
669
654
  if (!this.config) this.load();
670
- this.config.skills[name] = ref;
655
+ if (this.config) this.config.skills[name] = ref;
671
656
  this.save();
672
657
  }
673
658
  removeSkill(name) {
674
659
  if (!this.config) this.load();
675
- if (this.config.skills[name]) {
660
+ if (this.config?.skills[name]) {
676
661
  delete this.config.skills[name];
677
662
  this.save();
678
663
  return true;
@@ -685,7 +670,7 @@ class ConfigLoader {
685
670
  this.load();
686
671
  }
687
672
  return {
688
- ...this.config.skills
673
+ ...this.config?.skills
689
674
  };
690
675
  }
691
676
  hasSkill(name) {
@@ -697,247 +682,177 @@ class ConfigLoader {
697
682
  return skills[name];
698
683
  }
699
684
  }
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);
685
+ class GitResolver {
686
+ defaultRegistry;
687
+ constructor(defaultRegistry = 'github'){
688
+ this.defaultRegistry = defaultRegistry;
714
689
  }
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;
690
+ parseRef(ref) {
691
+ const raw = ref;
692
+ if (isGitUrl(ref)) return this.parseGitUrlRef(ref);
693
+ let remaining = ref;
694
+ let registry = this.defaultRegistry;
695
+ let version;
696
+ const registryMatch = remaining.match(/^([a-zA-Z0-9.-]+):(.+)$/);
697
+ if (registryMatch) {
698
+ registry = registryMatch[1];
699
+ remaining = registryMatch[2];
723
700
  }
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}`);
701
+ const atIndex = remaining.lastIndexOf('@');
702
+ if (atIndex > 0) {
703
+ version = remaining.slice(atIndex + 1);
704
+ remaining = remaining.slice(0, atIndex);
729
705
  }
706
+ const parts = remaining.split('/');
707
+ if (parts.length < 2) throw new Error(`Invalid skill reference: ${ref}. Expected format: owner/repo[@version]`);
708
+ const owner = parts[0];
709
+ const repo = parts[1];
710
+ const subPath = parts.length > 2 ? parts.slice(2).join('/') : void 0;
711
+ return {
712
+ registry,
713
+ owner,
714
+ repo,
715
+ subPath,
716
+ version,
717
+ raw
718
+ };
730
719
  }
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;
720
+ parseGitUrlRef(ref) {
721
+ const raw = ref;
722
+ let gitUrl = ref;
723
+ let version;
724
+ let subPath;
725
+ const gitSuffixIndex = ref.indexOf('.git');
726
+ if (-1 !== gitSuffixIndex) {
727
+ const afterGit = ref.slice(gitSuffixIndex + 4);
728
+ if (afterGit) {
729
+ const atIndex = afterGit.lastIndexOf('@');
730
+ if (-1 !== atIndex) {
731
+ version = afterGit.slice(atIndex + 1);
732
+ const pathPart = afterGit.slice(0, atIndex);
733
+ if (pathPart.startsWith('/')) subPath = pathPart.slice(1);
734
+ } else if (afterGit.startsWith('/')) subPath = afterGit.slice(1);
735
+ gitUrl = ref.slice(0, gitSuffixIndex + 4);
736
+ }
737
+ } else {
738
+ const atIndex = ref.lastIndexOf('@');
739
+ if (atIndex > 4) {
740
+ version = ref.slice(atIndex + 1);
741
+ gitUrl = ref.slice(0, atIndex);
742
+ }
756
743
  }
757
- return false;
744
+ const parsed = parseGitUrl(gitUrl);
745
+ if (!parsed) throw new Error(`Invalid Git URL: ${ref}. Expected format: git@host:owner/repo.git or https://host/owner/repo.git`);
746
+ return {
747
+ registry: parsed.host,
748
+ owner: parsed.owner,
749
+ repo: parsed.repo,
750
+ subPath,
751
+ version,
752
+ raw,
753
+ gitUrl
754
+ };
758
755
  }
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()
756
+ parseVersion(versionSpec) {
757
+ if (!versionSpec) return {
758
+ type: 'branch',
759
+ value: 'main',
760
+ raw: ''
766
761
  };
767
- this.set(name, lockedSkill);
768
- return lockedSkill;
762
+ const raw = versionSpec;
763
+ if ('latest' === versionSpec) return {
764
+ type: 'latest',
765
+ value: 'latest',
766
+ raw
767
+ };
768
+ if (versionSpec.startsWith('branch:')) return {
769
+ type: 'branch',
770
+ value: versionSpec.slice(7),
771
+ raw
772
+ };
773
+ if (versionSpec.startsWith('commit:')) return {
774
+ type: 'commit',
775
+ value: versionSpec.slice(7),
776
+ raw
777
+ };
778
+ if (/^[\^~><]/.test(versionSpec)) return {
779
+ type: 'range',
780
+ value: versionSpec,
781
+ raw
782
+ };
783
+ return {
784
+ type: 'exact',
785
+ value: versionSpec,
786
+ raw
787
+ };
788
+ }
789
+ buildRepoUrl(parsed) {
790
+ if (parsed.gitUrl) return parsed.gitUrl;
791
+ return buildRepoUrl(parsed.registry, `${parsed.owner}/${parsed.repo}`);
792
+ }
793
+ async resolveVersion(repoUrl, versionSpec) {
794
+ switch(versionSpec.type){
795
+ case 'exact':
796
+ return {
797
+ ref: versionSpec.value
798
+ };
799
+ case 'latest':
800
+ {
801
+ const latestTag = await getLatestTag(repoUrl);
802
+ if (!latestTag) {
803
+ const defaultBranch = await getDefaultBranch(repoUrl);
804
+ return {
805
+ ref: defaultBranch
806
+ };
807
+ }
808
+ return {
809
+ ref: latestTag.name,
810
+ commit: latestTag.commit
811
+ };
812
+ }
813
+ case 'range':
814
+ {
815
+ const tags = await getRemoteTags(repoUrl);
816
+ const matchingTags = tags.filter((tag)=>{
817
+ const version = tag.name.replace(/^v/, '');
818
+ return __WEBPACK_EXTERNAL_MODULE_semver__.satisfies(version, versionSpec.value);
819
+ });
820
+ if (0 === matchingTags.length) throw new Error(`No version found matching ${versionSpec.raw} for ${repoUrl}`);
821
+ matchingTags.sort((a, b)=>{
822
+ const aVer = a.name.replace(/^v/, '');
823
+ const bVer = b.name.replace(/^v/, '');
824
+ return __WEBPACK_EXTERNAL_MODULE_semver__.compare(bVer, aVer);
825
+ });
826
+ return {
827
+ ref: matchingTags[0].name,
828
+ commit: matchingTags[0].commit
829
+ };
830
+ }
831
+ case 'branch':
832
+ return {
833
+ ref: versionSpec.value
834
+ };
835
+ case 'commit':
836
+ return {
837
+ ref: versionSpec.value,
838
+ commit: versionSpec.value
839
+ };
840
+ default:
841
+ throw new Error(`Unknown version type: ${versionSpec.type}`);
842
+ }
769
843
  }
770
- getAll() {
771
- const lock = this.load();
844
+ async resolve(ref) {
845
+ const parsed = this.parseRef(ref);
846
+ const repoUrl = this.buildRepoUrl(parsed);
847
+ const versionSpec = this.parseVersion(parsed.version);
848
+ const resolved = await this.resolveVersion(repoUrl, versionSpec);
772
849
  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: {}
850
+ parsed,
851
+ repoUrl,
852
+ ref: resolved.ref,
853
+ commit: resolved.commit
789
854
  };
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
855
  }
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
856
  }
942
857
  const installer_AGENTS_DIR = '.agents';
943
858
  const installer_SKILLS_SUBDIR = 'skills';
@@ -955,7 +870,7 @@ function installer_isPathSafe(basePath, targetPath) {
955
870
  return normalizedTarget.startsWith(normalizedBase + __WEBPACK_EXTERNAL_MODULE_node_path__.sep) || normalizedTarget === normalizedBase;
956
871
  }
957
872
  function installer_getCanonicalSkillsDir(isGlobal, cwd) {
958
- const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_os__.homedir)() : cwd || process.cwd();
873
+ const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_node_os__.homedir)() : cwd || process.cwd();
959
874
  return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, installer_AGENTS_DIR, installer_SKILLS_SUBDIR);
960
875
  }
961
876
  function installer_ensureDir(dirPath) {
@@ -972,7 +887,8 @@ function installer_remove(targetPath) {
972
887
  function copyDirectory(src, dest, options) {
973
888
  const exclude = new Set(options?.exclude || [
974
889
  'README.md',
975
- 'metadata.json'
890
+ 'metadata.json',
891
+ '.reskill-commit'
976
892
  ]);
977
893
  installer_ensureDir(dest);
978
894
  const entries = external_node_fs_.readdirSync(src, {
@@ -1009,7 +925,7 @@ async function installer_createSymlink(target, linkPath) {
1009
925
  const linkDir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath);
1010
926
  installer_ensureDir(linkDir);
1011
927
  const relativePath = __WEBPACK_EXTERNAL_MODULE_node_path__.relative(linkDir, target);
1012
- const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_os__.platform)() ? 'junction' : void 0;
928
+ const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_node_os__.platform)() ? 'junction' : void 0;
1013
929
  external_node_fs_.symlinkSync(relativePath, linkPath, symlinkType);
1014
930
  return true;
1015
931
  } catch {
@@ -1132,6 +1048,106 @@ class Installer {
1132
1048
  }).filter((entry)=>entry.isDirectory() || entry.isSymbolicLink()).map((entry)=>entry.name);
1133
1049
  }
1134
1050
  }
1051
+ const LOCKFILE_VERSION = 1;
1052
+ class LockManager {
1053
+ projectRoot;
1054
+ lockPath;
1055
+ lockData = null;
1056
+ constructor(projectRoot){
1057
+ this.projectRoot = projectRoot || process.cwd();
1058
+ this.lockPath = getSkillsLockPath(this.projectRoot);
1059
+ }
1060
+ getLockPath() {
1061
+ return this.lockPath;
1062
+ }
1063
+ exists() {
1064
+ return exists(this.lockPath);
1065
+ }
1066
+ load() {
1067
+ if (this.lockData) return this.lockData;
1068
+ if (!this.exists()) {
1069
+ this.lockData = {
1070
+ lockfileVersion: LOCKFILE_VERSION,
1071
+ skills: {}
1072
+ };
1073
+ return this.lockData;
1074
+ }
1075
+ try {
1076
+ this.lockData = readJson(this.lockPath);
1077
+ return this.lockData;
1078
+ } catch (error) {
1079
+ throw new Error(`Failed to parse skills.lock: ${error.message}`);
1080
+ }
1081
+ }
1082
+ reload() {
1083
+ this.lockData = null;
1084
+ return this.load();
1085
+ }
1086
+ save(lockToSave) {
1087
+ const toSave = lockToSave || this.lockData;
1088
+ if (!toSave) throw new Error('No lock to save');
1089
+ writeJson(this.lockPath, toSave);
1090
+ this.lockData = toSave;
1091
+ }
1092
+ get(name) {
1093
+ const lock = this.load();
1094
+ return lock.skills[name];
1095
+ }
1096
+ set(name, skill) {
1097
+ const lock = this.load();
1098
+ lock.skills[name] = skill;
1099
+ this.save();
1100
+ }
1101
+ remove(name) {
1102
+ const lock = this.load();
1103
+ if (lock.skills[name]) {
1104
+ delete lock.skills[name];
1105
+ this.save();
1106
+ return true;
1107
+ }
1108
+ return false;
1109
+ }
1110
+ lockSkill(name, options) {
1111
+ const lockedSkill = {
1112
+ source: options.source,
1113
+ version: options.version,
1114
+ resolved: options.resolved,
1115
+ commit: options.commit,
1116
+ installedAt: new Date().toISOString()
1117
+ };
1118
+ this.set(name, lockedSkill);
1119
+ return lockedSkill;
1120
+ }
1121
+ getAll() {
1122
+ const lock = this.load();
1123
+ return {
1124
+ ...lock.skills
1125
+ };
1126
+ }
1127
+ has(name) {
1128
+ const lock = this.load();
1129
+ return name in lock.skills;
1130
+ }
1131
+ isVersionMatch(name, version) {
1132
+ const locked = this.get(name);
1133
+ if (!locked) return false;
1134
+ return locked.version === version;
1135
+ }
1136
+ clear() {
1137
+ this.lockData = {
1138
+ lockfileVersion: LOCKFILE_VERSION,
1139
+ skills: {}
1140
+ };
1141
+ this.save();
1142
+ }
1143
+ delete() {
1144
+ if (this.exists()) {
1145
+ const fs = __webpack_require__("node:fs");
1146
+ fs.unlinkSync(this.lockPath);
1147
+ }
1148
+ this.lockData = null;
1149
+ }
1150
+ }
1135
1151
  const logger = {
1136
1152
  info (message) {
1137
1153
  console.log(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].blue('ℹ'), message);
@@ -1199,8 +1215,17 @@ class SkillManager {
1199
1215
  if (this.isGlobal) return getGlobalSkillsDir();
1200
1216
  return this.config.getInstallDir();
1201
1217
  }
1218
+ getCanonicalSkillsDir() {
1219
+ const home = process.env.HOME || process.env.USERPROFILE || '';
1220
+ const baseDir = this.isGlobal ? home : this.projectRoot;
1221
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, '.agents', 'skills');
1222
+ }
1202
1223
  getSkillPath(name) {
1203
- return __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1224
+ const canonicalPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getCanonicalSkillsDir(), name);
1225
+ if (exists(canonicalPath)) return canonicalPath;
1226
+ const legacyPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1227
+ if (exists(legacyPath)) return legacyPath;
1228
+ return canonicalPath;
1204
1229
  }
1205
1230
  async install(ref, options = {}) {
1206
1231
  const { force = false, save = true } = options;
@@ -1213,11 +1238,13 @@ class SkillManager {
1213
1238
  const locked = this.lockManager.get(skillName);
1214
1239
  if (locked && locked.version === version) {
1215
1240
  logger.info(`${skillName}@${version} is already installed`);
1216
- return this.getInstalledSkill(skillName);
1241
+ const installed = this.getInstalledSkill(skillName);
1242
+ if (installed) return installed;
1217
1243
  }
1218
1244
  if (!force) {
1219
1245
  logger.warn(`${skillName} is already installed. Use --force to reinstall.`);
1220
- return this.getInstalledSkill(skillName);
1246
+ const installed = this.getInstalledSkill(skillName);
1247
+ if (installed) return installed;
1221
1248
  }
1222
1249
  }
1223
1250
  logger["package"](`Installing ${skillName}@${version}...`);
@@ -1231,15 +1258,20 @@ class SkillManager {
1231
1258
  if (exists(skillPath)) remove(skillPath);
1232
1259
  await this.cache.copyTo(parsed, version, skillPath);
1233
1260
  if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
1234
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`,
1261
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
1235
1262
  version,
1236
1263
  resolved: repoUrl,
1237
1264
  commit: cacheResult.commit
1238
1265
  });
1239
- if (!this.isGlobal && save && this.config.exists()) this.config.addSkill(skillName, ref);
1266
+ if (!this.isGlobal && save) {
1267
+ this.config.ensureExists();
1268
+ this.config.addSkill(skillName, ref);
1269
+ }
1240
1270
  const locationHint = this.isGlobal ? '(global)' : '';
1241
1271
  logger.success(`Installed ${skillName}@${version} to ${skillPath} ${locationHint}`.trim());
1242
- return this.getInstalledSkill(skillName);
1272
+ const installed = this.getInstalledSkill(skillName);
1273
+ if (!installed) throw new Error(`Failed to get installed skill info for ${skillName}`);
1274
+ return installed;
1243
1275
  }
1244
1276
  async installAll(options = {}) {
1245
1277
  const skills = this.config.getSkills();
@@ -1306,7 +1338,7 @@ class SkillManager {
1306
1338
  skillName = name || skillJson.name || skillName;
1307
1339
  } catch {}
1308
1340
  const linkPath = this.getSkillPath(skillName);
1309
- ensureDir(this.getInstallDir());
1341
+ ensureDir(__WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath));
1310
1342
  createSymlink(absolutePath, linkPath);
1311
1343
  logger.success(`Linked ${skillName} → ${absolutePath}`);
1312
1344
  return {
@@ -1332,20 +1364,36 @@ class SkillManager {
1332
1364
  return true;
1333
1365
  }
1334
1366
  list() {
1335
- const installDir = this.getInstallDir();
1336
- if (!exists(installDir)) return [];
1337
1367
  const skills = [];
1338
- const dirs = listDir(installDir);
1339
- for (const name of dirs){
1340
- const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(installDir, name);
1368
+ const seenNames = new Set();
1369
+ const canonicalDir = this.getCanonicalSkillsDir();
1370
+ if (exists(canonicalDir)) for (const name of listDir(canonicalDir)){
1371
+ const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalDir, name);
1372
+ if (!isDirectory(skillPath)) continue;
1373
+ const skill = this.getInstalledSkillFromPath(name, skillPath);
1374
+ if (skill) {
1375
+ skills.push(skill);
1376
+ seenNames.add(name);
1377
+ }
1378
+ }
1379
+ const legacyDir = this.getInstallDir();
1380
+ if (exists(legacyDir) && legacyDir !== canonicalDir) for (const name of listDir(legacyDir)){
1381
+ if (seenNames.has(name)) continue;
1382
+ const skillPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(legacyDir, name);
1341
1383
  if (!isDirectory(skillPath)) continue;
1342
- const skill = this.getInstalledSkill(name);
1343
- if (skill) skills.push(skill);
1384
+ if (isSymlink(skillPath)) try {
1385
+ const realPath = getRealPath(skillPath);
1386
+ if (realPath.includes(__WEBPACK_EXTERNAL_MODULE_node_path__.join('.agents', 'skills'))) continue;
1387
+ } catch {}
1388
+ const skill = this.getInstalledSkillFromPath(name, skillPath);
1389
+ if (skill) {
1390
+ skills.push(skill);
1391
+ seenNames.add(name);
1392
+ }
1344
1393
  }
1345
1394
  return skills;
1346
1395
  }
1347
- getInstalledSkill(name) {
1348
- const skillPath = this.getSkillPath(name);
1396
+ getInstalledSkillFromPath(name, skillPath) {
1349
1397
  if (!exists(skillPath)) return null;
1350
1398
  const isLinked = isSymlink(skillPath);
1351
1399
  const locked = this.lockManager.get(name);
@@ -1363,6 +1411,13 @@ class SkillManager {
1363
1411
  isLinked
1364
1412
  };
1365
1413
  }
1414
+ getInstalledSkill(name) {
1415
+ const canonicalPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getCanonicalSkillsDir(), name);
1416
+ if (exists(canonicalPath)) return this.getInstalledSkillFromPath(name, canonicalPath);
1417
+ const legacyPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.getInstallDir(), name);
1418
+ if (exists(legacyPath)) return this.getInstalledSkillFromPath(name, legacyPath);
1419
+ return null;
1420
+ }
1366
1421
  getInfo(name) {
1367
1422
  return {
1368
1423
  installed: this.getInstalledSkill(name),
@@ -1424,12 +1479,15 @@ class SkillManager {
1424
1479
  mode: mode
1425
1480
  });
1426
1481
  if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
1427
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`,
1482
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`,
1428
1483
  version,
1429
1484
  resolved: repoUrl,
1430
1485
  commit: cacheResult.commit
1431
1486
  });
1432
- if (!this.isGlobal && save && this.config.exists()) this.config.addSkill(skillName, ref);
1487
+ if (!this.isGlobal && save) {
1488
+ this.config.ensureExists();
1489
+ this.config.addSkill(skillName, ref);
1490
+ }
1433
1491
  const successCount = Array.from(results.values()).filter((r)=>r.success).length;
1434
1492
  const failCount = results.size - successCount;
1435
1493
  if (0 === failCount) logger.success(`Installed ${skillName}@${version} to ${successCount} agent(s)`);
@@ -1438,7 +1496,7 @@ class SkillManager {
1438
1496
  name: skillName,
1439
1497
  path: sourcePath,
1440
1498
  version,
1441
- source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`
1499
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? `/${parsed.subPath}` : ''}`
1442
1500
  };
1443
1501
  return {
1444
1502
  skill,