reskill 0.1.0 → 0.11.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.
package/dist/cli/index.js CHANGED
@@ -3,10 +3,14 @@ import * as __WEBPACK_EXTERNAL_MODULE_node_fs__ from "node:fs";
3
3
  import * as __WEBPACK_EXTERNAL_MODULE_commander__ from "commander";
4
4
  import * as __WEBPACK_EXTERNAL_MODULE_node_path__ from "node:path";
5
5
  import * as __WEBPACK_EXTERNAL_MODULE_chalk__ from "chalk";
6
- import * as __WEBPACK_EXTERNAL_MODULE_ora__ from "ora";
6
+ import * as __WEBPACK_EXTERNAL_MODULE__clack_prompts__ from "@clack/prompts";
7
7
  import * as __WEBPACK_EXTERNAL_MODULE_semver__ from "semver";
8
8
  import * as __WEBPACK_EXTERNAL_MODULE_node_child_process__ from "node:child_process";
9
9
  import * as __WEBPACK_EXTERNAL_MODULE_node_util__ from "node:util";
10
+ import * as __WEBPACK_EXTERNAL_MODULE_os__ from "os";
11
+ import * as __WEBPACK_EXTERNAL_MODULE_path__ from "path";
12
+ import * as __WEBPACK_EXTERNAL_MODULE_fs__ from "fs";
13
+ import * as __WEBPACK_EXTERNAL_MODULE_ora__ from "ora";
10
14
  var __webpack_modules__ = {
11
15
  "node:fs": function(module) {
12
16
  module.exports = __WEBPACK_EXTERNAL_MODULE_node_fs__;
@@ -102,6 +106,13 @@ function getGlobalSkillsDir() {
102
106
  const home = getHomeDir();
103
107
  return __WEBPACK_EXTERNAL_MODULE_node_path__.join(home, '.claude', 'skills');
104
108
  }
109
+ function shortenPath(fullPath, cwd) {
110
+ const home = getHomeDir();
111
+ const currentDir = cwd || process.cwd();
112
+ if (fullPath.startsWith(home)) return fullPath.replace(home, '~');
113
+ if (fullPath.startsWith(currentDir)) return '.' + fullPath.slice(currentDir.length);
114
+ return fullPath;
115
+ }
105
116
  const DEFAULT_SKILLS_JSON = {
106
117
  skills: {},
107
118
  defaults: {
@@ -167,7 +178,9 @@ class ConfigLoader {
167
178
  const config = this.config || (this.exists() ? this.load() : DEFAULT_SKILLS_JSON);
168
179
  return {
169
180
  registry: config.defaults?.registry || DEFAULT_SKILLS_JSON.defaults.registry,
170
- installDir: config.defaults?.installDir || DEFAULT_SKILLS_JSON.defaults.installDir
181
+ installDir: config.defaults?.installDir || DEFAULT_SKILLS_JSON.defaults.installDir,
182
+ targetAgents: config.defaults?.targetAgents || [],
183
+ installMode: config.defaults?.installMode || 'symlink'
171
184
  };
172
185
  }
173
186
  getRegistryUrl(registryName) {
@@ -630,6 +643,9 @@ class CacheManager {
630
643
  getSkillCachePath(parsed, version) {
631
644
  return __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cacheDir, parsed.registry, parsed.owner, parsed.repo, version);
632
645
  }
646
+ getCachePath(parsed, version) {
647
+ return this.getSkillCachePath(parsed, version);
648
+ }
633
649
  isCached(parsed, version) {
634
650
  const cachePath = this.getSkillCachePath(parsed, version);
635
651
  return exists(cachePath) && isDirectory(cachePath);
@@ -827,6 +843,332 @@ class LockManager {
827
843
  this.lockData = null;
828
844
  }
829
845
  }
846
+ const agent_registry_home = (0, __WEBPACK_EXTERNAL_MODULE_os__.homedir)();
847
+ const agents = {
848
+ amp: {
849
+ name: 'amp',
850
+ displayName: 'Amp',
851
+ skillsDir: '.agents/skills',
852
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/agents/skills'),
853
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/amp'))
854
+ },
855
+ antigravity: {
856
+ name: 'antigravity',
857
+ displayName: 'Antigravity',
858
+ skillsDir: '.agent/skills',
859
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/antigravity/skills'),
860
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(process.cwd(), '.agent')) || (0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/antigravity'))
861
+ },
862
+ 'claude-code': {
863
+ name: 'claude-code',
864
+ displayName: 'Claude Code',
865
+ skillsDir: '.claude/skills',
866
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude/skills'),
867
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude'))
868
+ },
869
+ clawdbot: {
870
+ name: 'clawdbot',
871
+ displayName: 'Clawdbot',
872
+ skillsDir: 'skills',
873
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.clawdbot/skills'),
874
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.clawdbot'))
875
+ },
876
+ codex: {
877
+ name: 'codex',
878
+ displayName: 'Codex',
879
+ skillsDir: '.codex/skills',
880
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codex/skills'),
881
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codex'))
882
+ },
883
+ cursor: {
884
+ name: 'cursor',
885
+ displayName: 'Cursor',
886
+ skillsDir: '.cursor/skills',
887
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.cursor/skills'),
888
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.cursor'))
889
+ },
890
+ droid: {
891
+ name: 'droid',
892
+ displayName: 'Droid',
893
+ skillsDir: '.factory/skills',
894
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.factory/skills'),
895
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.factory/skills'))
896
+ },
897
+ 'gemini-cli': {
898
+ name: 'gemini-cli',
899
+ displayName: 'Gemini CLI',
900
+ skillsDir: '.gemini/skills',
901
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini/skills'),
902
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.gemini'))
903
+ },
904
+ 'github-copilot': {
905
+ name: 'github-copilot',
906
+ displayName: 'GitHub Copilot',
907
+ skillsDir: '.github/skills',
908
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.copilot/skills'),
909
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(process.cwd(), '.github')) || (0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.copilot'))
910
+ },
911
+ goose: {
912
+ name: 'goose',
913
+ displayName: 'Goose',
914
+ skillsDir: '.goose/skills',
915
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/goose/skills'),
916
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/goose'))
917
+ },
918
+ kilo: {
919
+ name: 'kilo',
920
+ displayName: 'Kilo Code',
921
+ skillsDir: '.kilocode/skills',
922
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kilocode/skills'),
923
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kilocode'))
924
+ },
925
+ 'kiro-cli': {
926
+ name: 'kiro-cli',
927
+ displayName: 'Kiro CLI',
928
+ skillsDir: '.kiro/skills',
929
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kiro/skills'),
930
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.kiro'))
931
+ },
932
+ opencode: {
933
+ name: 'opencode',
934
+ displayName: 'OpenCode',
935
+ skillsDir: '.opencode/skills',
936
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/opencode/skills'),
937
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.config/opencode')) || (0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.claude/skills'))
938
+ },
939
+ roo: {
940
+ name: 'roo',
941
+ displayName: 'Roo Code',
942
+ skillsDir: '.roo/skills',
943
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.roo/skills'),
944
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.roo'))
945
+ },
946
+ trae: {
947
+ name: 'trae',
948
+ displayName: 'Trae',
949
+ skillsDir: '.trae/skills',
950
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.trae/skills'),
951
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.trae'))
952
+ },
953
+ windsurf: {
954
+ name: 'windsurf',
955
+ displayName: 'Windsurf',
956
+ skillsDir: '.windsurf/skills',
957
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codeium/windsurf/skills'),
958
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.codeium/windsurf'))
959
+ },
960
+ neovate: {
961
+ name: 'neovate',
962
+ displayName: 'Neovate',
963
+ skillsDir: '.neovate/skills',
964
+ globalSkillsDir: (0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.neovate/skills'),
965
+ detectInstalled: async ()=>(0, __WEBPACK_EXTERNAL_MODULE_fs__.existsSync)((0, __WEBPACK_EXTERNAL_MODULE_path__.join)(agent_registry_home, '.neovate'))
966
+ }
967
+ };
968
+ async function detectInstalledAgents() {
969
+ const installed = [];
970
+ for (const [type, config] of Object.entries(agents))if (await config.detectInstalled()) installed.push(type);
971
+ return installed;
972
+ }
973
+ function getAgentConfig(type) {
974
+ return agents[type];
975
+ }
976
+ function isValidAgentType(type) {
977
+ return type in agents;
978
+ }
979
+ const installer_AGENTS_DIR = '.agents';
980
+ const installer_SKILLS_SUBDIR = 'skills';
981
+ function installer_sanitizeName(name) {
982
+ let sanitized = name.replace(/[/\\:\0]/g, '');
983
+ sanitized = sanitized.replace(/^[.\s]+|[.\s]+$/g, '');
984
+ sanitized = sanitized.replace(/^\.+/, '');
985
+ if (!sanitized || 0 === sanitized.length) sanitized = 'unnamed-skill';
986
+ if (sanitized.length > 255) sanitized = sanitized.substring(0, 255);
987
+ return sanitized;
988
+ }
989
+ function installer_isPathSafe(basePath, targetPath) {
990
+ const normalizedBase = __WEBPACK_EXTERNAL_MODULE_node_path__.normalize(__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(basePath));
991
+ const normalizedTarget = __WEBPACK_EXTERNAL_MODULE_node_path__.normalize(__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(targetPath));
992
+ return normalizedTarget.startsWith(normalizedBase + __WEBPACK_EXTERNAL_MODULE_node_path__.sep) || normalizedTarget === normalizedBase;
993
+ }
994
+ function installer_getCanonicalSkillsDir(isGlobal, cwd) {
995
+ const baseDir = isGlobal ? (0, __WEBPACK_EXTERNAL_MODULE_os__.homedir)() : cwd || process.cwd();
996
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(baseDir, installer_AGENTS_DIR, installer_SKILLS_SUBDIR);
997
+ }
998
+ function installer_ensureDir(dirPath) {
999
+ if (!external_node_fs_.existsSync(dirPath)) external_node_fs_.mkdirSync(dirPath, {
1000
+ recursive: true
1001
+ });
1002
+ }
1003
+ function installer_remove(targetPath) {
1004
+ if (external_node_fs_.existsSync(targetPath)) external_node_fs_.rmSync(targetPath, {
1005
+ recursive: true,
1006
+ force: true
1007
+ });
1008
+ }
1009
+ function copyDirectory(src, dest, options) {
1010
+ const exclude = new Set(options?.exclude || [
1011
+ 'README.md',
1012
+ 'metadata.json'
1013
+ ]);
1014
+ installer_ensureDir(dest);
1015
+ const entries = external_node_fs_.readdirSync(src, {
1016
+ withFileTypes: true
1017
+ });
1018
+ for (const entry of entries){
1019
+ if (exclude.has(entry.name) || entry.name.startsWith('_')) continue;
1020
+ const srcPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(src, entry.name);
1021
+ const destPath = __WEBPACK_EXTERNAL_MODULE_node_path__.join(dest, entry.name);
1022
+ if (entry.isDirectory()) copyDirectory(srcPath, destPath, options);
1023
+ else external_node_fs_.copyFileSync(srcPath, destPath);
1024
+ }
1025
+ }
1026
+ async function installer_createSymlink(target, linkPath) {
1027
+ try {
1028
+ try {
1029
+ const stats = external_node_fs_.lstatSync(linkPath);
1030
+ if (stats.isSymbolicLink()) {
1031
+ const existingTarget = external_node_fs_.readlinkSync(linkPath);
1032
+ if (__WEBPACK_EXTERNAL_MODULE_node_path__.resolve(existingTarget) === __WEBPACK_EXTERNAL_MODULE_node_path__.resolve(target)) return true;
1033
+ external_node_fs_.rmSync(linkPath);
1034
+ } else external_node_fs_.rmSync(linkPath, {
1035
+ recursive: true
1036
+ });
1037
+ } catch (err) {
1038
+ if (err && 'object' == typeof err && 'code' in err) {
1039
+ if ('ELOOP' === err.code) try {
1040
+ external_node_fs_.rmSync(linkPath, {
1041
+ force: true
1042
+ });
1043
+ } catch {}
1044
+ }
1045
+ }
1046
+ const linkDir = __WEBPACK_EXTERNAL_MODULE_node_path__.dirname(linkPath);
1047
+ installer_ensureDir(linkDir);
1048
+ const relativePath = __WEBPACK_EXTERNAL_MODULE_node_path__.relative(linkDir, target);
1049
+ const symlinkType = 'win32' === (0, __WEBPACK_EXTERNAL_MODULE_os__.platform)() ? 'junction' : void 0;
1050
+ external_node_fs_.symlinkSync(relativePath, linkPath, symlinkType);
1051
+ return true;
1052
+ } catch {
1053
+ return false;
1054
+ }
1055
+ }
1056
+ class Installer {
1057
+ cwd;
1058
+ isGlobal;
1059
+ constructor(options = {}){
1060
+ this.cwd = options.cwd || process.cwd();
1061
+ this.isGlobal = options.global || false;
1062
+ }
1063
+ getCanonicalPath(skillName) {
1064
+ const sanitized = installer_sanitizeName(skillName);
1065
+ const canonicalBase = installer_getCanonicalSkillsDir(this.isGlobal, this.cwd);
1066
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalBase, sanitized);
1067
+ }
1068
+ getAgentSkillPath(skillName, agentType) {
1069
+ const agent = getAgentConfig(agentType);
1070
+ const sanitized = installer_sanitizeName(skillName);
1071
+ const agentBase = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
1072
+ return __WEBPACK_EXTERNAL_MODULE_node_path__.join(agentBase, sanitized);
1073
+ }
1074
+ async installForAgent(sourcePath, skillName, agentType, options = {}) {
1075
+ const agent = getAgentConfig(agentType);
1076
+ const installMode = options.mode || 'symlink';
1077
+ const sanitized = installer_sanitizeName(skillName);
1078
+ const canonicalBase = installer_getCanonicalSkillsDir(this.isGlobal, this.cwd);
1079
+ const canonicalDir = __WEBPACK_EXTERNAL_MODULE_node_path__.join(canonicalBase, sanitized);
1080
+ const agentBase = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
1081
+ const agentDir = __WEBPACK_EXTERNAL_MODULE_node_path__.join(agentBase, sanitized);
1082
+ if (!installer_isPathSafe(canonicalBase, canonicalDir)) return {
1083
+ success: false,
1084
+ path: agentDir,
1085
+ mode: installMode,
1086
+ error: 'Invalid skill name: potential path traversal detected'
1087
+ };
1088
+ if (!installer_isPathSafe(agentBase, agentDir)) return {
1089
+ success: false,
1090
+ path: agentDir,
1091
+ mode: installMode,
1092
+ error: 'Invalid skill name: potential path traversal detected'
1093
+ };
1094
+ try {
1095
+ if ('copy' === installMode) {
1096
+ installer_ensureDir(agentDir);
1097
+ installer_remove(agentDir);
1098
+ copyDirectory(sourcePath, agentDir);
1099
+ return {
1100
+ success: true,
1101
+ path: agentDir,
1102
+ mode: 'copy'
1103
+ };
1104
+ }
1105
+ installer_ensureDir(canonicalDir);
1106
+ installer_remove(canonicalDir);
1107
+ copyDirectory(sourcePath, canonicalDir);
1108
+ const symlinkCreated = await installer_createSymlink(canonicalDir, agentDir);
1109
+ if (!symlinkCreated) {
1110
+ try {
1111
+ installer_remove(agentDir);
1112
+ } catch {}
1113
+ installer_ensureDir(agentDir);
1114
+ copyDirectory(sourcePath, agentDir);
1115
+ return {
1116
+ success: true,
1117
+ path: agentDir,
1118
+ canonicalPath: canonicalDir,
1119
+ mode: 'symlink',
1120
+ symlinkFailed: true
1121
+ };
1122
+ }
1123
+ return {
1124
+ success: true,
1125
+ path: agentDir,
1126
+ canonicalPath: canonicalDir,
1127
+ mode: 'symlink'
1128
+ };
1129
+ } catch (error) {
1130
+ return {
1131
+ success: false,
1132
+ path: agentDir,
1133
+ mode: installMode,
1134
+ error: error instanceof Error ? error.message : 'Unknown error'
1135
+ };
1136
+ }
1137
+ }
1138
+ async installToAgents(sourcePath, skillName, targetAgents, options = {}) {
1139
+ const results = new Map();
1140
+ for (const agent of targetAgents){
1141
+ const result = await this.installForAgent(sourcePath, skillName, agent, options);
1142
+ results.set(agent, result);
1143
+ }
1144
+ return results;
1145
+ }
1146
+ isInstalled(skillName, agentType) {
1147
+ const skillPath = this.getAgentSkillPath(skillName, agentType);
1148
+ return external_node_fs_.existsSync(skillPath);
1149
+ }
1150
+ uninstallFromAgent(skillName, agentType) {
1151
+ const skillPath = this.getAgentSkillPath(skillName, agentType);
1152
+ if (!external_node_fs_.existsSync(skillPath)) return false;
1153
+ installer_remove(skillPath);
1154
+ return true;
1155
+ }
1156
+ uninstallFromAgents(skillName, targetAgents) {
1157
+ const results = new Map();
1158
+ for (const agent of targetAgents)results.set(agent, this.uninstallFromAgent(skillName, agent));
1159
+ const canonicalPath = this.getCanonicalPath(skillName);
1160
+ if (external_node_fs_.existsSync(canonicalPath)) installer_remove(canonicalPath);
1161
+ return results;
1162
+ }
1163
+ listInstalledSkills(agentType) {
1164
+ const agent = getAgentConfig(agentType);
1165
+ const skillsDir = this.isGlobal ? agent.globalSkillsDir : __WEBPACK_EXTERNAL_MODULE_node_path__.join(this.cwd, agent.skillsDir);
1166
+ if (!external_node_fs_.existsSync(skillsDir)) return [];
1167
+ return external_node_fs_.readdirSync(skillsDir, {
1168
+ withFileTypes: true
1169
+ }).filter((entry)=>entry.isDirectory() || entry.isSymbolicLink()).map((entry)=>entry.name);
1170
+ }
1171
+ }
830
1172
  class SkillManager {
831
1173
  projectRoot;
832
1174
  resolver;
@@ -1056,57 +1398,327 @@ class SkillManager {
1056
1398
  }
1057
1399
  return results;
1058
1400
  }
1401
+ async installToAgents(ref, targetAgents, options = {}) {
1402
+ const { save = true, mode = 'symlink' } = options;
1403
+ const resolved = await this.resolver.resolve(ref);
1404
+ const { parsed, repoUrl } = resolved;
1405
+ const version = resolved.ref;
1406
+ const skillName = parsed.subPath ? __WEBPACK_EXTERNAL_MODULE_node_path__.basename(parsed.subPath) : parsed.repo;
1407
+ logger["package"](`Installing ${skillName}@${version} to ${targetAgents.length} agent(s)...`);
1408
+ let cacheResult = await this.cache.get(parsed, version);
1409
+ if (cacheResult) logger.debug(`Using cached ${skillName}@${version}`);
1410
+ else {
1411
+ logger.debug(`Caching ${skillName}@${version} from ${repoUrl}`);
1412
+ cacheResult = await this.cache.cache(repoUrl, parsed, version, version);
1413
+ }
1414
+ const sourcePath = this.cache.getCachePath(parsed, version);
1415
+ const installer = new Installer({
1416
+ cwd: this.projectRoot,
1417
+ global: this.isGlobal
1418
+ });
1419
+ const results = await installer.installToAgents(sourcePath, skillName, targetAgents, {
1420
+ mode: mode
1421
+ });
1422
+ if (!this.isGlobal) this.lockManager.lockSkill(skillName, {
1423
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`,
1424
+ version,
1425
+ resolved: repoUrl,
1426
+ commit: cacheResult.commit
1427
+ });
1428
+ if (!this.isGlobal && save && this.config.exists()) this.config.addSkill(skillName, ref);
1429
+ const successCount = Array.from(results.values()).filter((r)=>r.success).length;
1430
+ const failCount = results.size - successCount;
1431
+ if (0 === failCount) logger.success(`Installed ${skillName}@${version} to ${successCount} agent(s)`);
1432
+ else logger.warn(`Installed ${skillName}@${version} to ${successCount} agent(s), ${failCount} failed`);
1433
+ const skill = {
1434
+ name: skillName,
1435
+ path: sourcePath,
1436
+ version,
1437
+ source: `${parsed.registry}:${parsed.owner}/${parsed.repo}${parsed.subPath ? '/' + parsed.subPath : ''}`
1438
+ };
1439
+ return {
1440
+ skill,
1441
+ results
1442
+ };
1443
+ }
1444
+ async getDefaultTargetAgents() {
1445
+ const defaults = this.config.getDefaults();
1446
+ if (defaults.targetAgents && defaults.targetAgents.length > 0) return defaults.targetAgents.filter(isValidAgentType);
1447
+ return detectInstalledAgents();
1448
+ }
1449
+ getDefaultInstallMode() {
1450
+ const defaults = this.config.getDefaults();
1451
+ if ('copy' === defaults.installMode || 'symlink' === defaults.installMode) return defaults.installMode;
1452
+ return 'symlink';
1453
+ }
1454
+ validateAgentTypes(agentNames) {
1455
+ const valid = [];
1456
+ const invalid = [];
1457
+ for (const name of agentNames)if (isValidAgentType(name)) valid.push(name);
1458
+ else invalid.push(name);
1459
+ return {
1460
+ valid,
1461
+ invalid
1462
+ };
1463
+ }
1464
+ getAllAgentTypes() {
1465
+ return Object.keys(agents);
1466
+ }
1467
+ uninstallFromAgents(name, targetAgents) {
1468
+ const installer = new Installer({
1469
+ cwd: this.projectRoot,
1470
+ global: this.isGlobal
1471
+ });
1472
+ const results = installer.uninstallFromAgents(name, targetAgents);
1473
+ if (!this.isGlobal) this.lockManager.remove(name);
1474
+ if (!this.isGlobal && this.config.exists()) this.config.removeSkill(name);
1475
+ const successCount = Array.from(results.values()).filter((r)=>r).length;
1476
+ logger.success(`Uninstalled ${name} from ${successCount} agent(s)`);
1477
+ return results;
1478
+ }
1059
1479
  }
1060
- const installCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('install').alias('i').description('Install a skill or all skills from skills.json').argument('[skill]', 'Skill reference (e.g., github:user/skill@v1.0.0 or git@github.com:user/repo.git)').option('-f, --force', 'Force reinstall even if already installed').option('-g, --global', 'Install globally to ~/.claude/skills').option('--no-save', 'Do not save to skills.json').action(async (skill, options)=>{
1061
- const isGlobal = options.global || false;
1480
+ function formatAgentNames(agentTypes, maxShow = 5) {
1481
+ const names = agentTypes.map((a)=>agents[a].displayName);
1482
+ if (names.length <= maxShow) return names.join(', ');
1483
+ const shown = names.slice(0, maxShow);
1484
+ const remaining = names.length - maxShow;
1485
+ return `${shown.join(', ')} +${remaining} more`;
1486
+ }
1487
+ const installCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('install').alias('i').description('Install a skill or all skills from skills.json').argument('[skill]', 'Skill reference (e.g., github:user/skill@v1.0.0 or git@github.com:user/repo.git)').option('-f, --force', 'Force reinstall even if already installed').option('-g, --global', 'Install globally to user home directory').option('--no-save', 'Do not save to skills.json').option('-a, --agent <agents...>', 'Specify target agents (e.g., cursor, claude-code)').option('--mode <mode>', 'Installation mode: symlink or copy').option('-y, --yes', 'Skip confirmation prompts').option('--all', 'Install to all agents (implies -y -g)').action(async (skill, options)=>{
1488
+ if (options.all) {
1489
+ options.yes = true;
1490
+ options.global = true;
1491
+ }
1492
+ const skipConfirm = options.yes || false;
1062
1493
  const configLoader = new ConfigLoader();
1063
- const skillManager = new SkillManager(void 0, {
1064
- global: isGlobal
1065
- });
1066
- if (isGlobal) logger.info(`Installing to ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].cyan(getGlobalSkillsDir())} ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('(global)')}`);
1067
- if (skill) {
1068
- const spinner = (0, __WEBPACK_EXTERNAL_MODULE_ora__["default"])(`Installing ${skill}...`).start();
1069
- try {
1070
- const installed = await skillManager.install(skill, {
1071
- force: options.force,
1072
- save: options.save && !isGlobal,
1073
- global: isGlobal
1074
- });
1075
- const location = isGlobal ? __WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim(' (global)') : '';
1076
- spinner.succeed(`Installed ${installed.name}@${installed.version}${location}`);
1077
- } catch (error) {
1078
- spinner.fail('Installation failed');
1079
- logger.error(error.message);
1080
- process.exit(1);
1081
- }
1082
- } else {
1083
- if (isGlobal) {
1084
- logger.error('Cannot install all skills globally. Please specify a skill to install.');
1085
- process.exit(1);
1494
+ const allAgentTypes = Object.keys(agents);
1495
+ console.log();
1496
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.intro(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].bgCyan.black(' reskill '));
1497
+ try {
1498
+ const spinner = __WEBPACK_EXTERNAL_MODULE__clack_prompts__.spinner();
1499
+ let targetAgents;
1500
+ if (options.all) {
1501
+ targetAgents = allAgentTypes;
1502
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.info(`Installing to all ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].cyan(targetAgents.length)} agents`);
1503
+ } else if (options.agent && options.agent.length > 0) {
1504
+ const validAgents = Object.keys(agents);
1505
+ const invalidAgents = options.agent.filter((a)=>!validAgents.includes(a));
1506
+ if (invalidAgents.length > 0) {
1507
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.error(`Invalid agents: ${invalidAgents.join(', ')}`);
1508
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.info(`Valid agents: ${validAgents.join(', ')}`);
1509
+ process.exit(1);
1510
+ }
1511
+ targetAgents = options.agent;
1512
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.info(`Installing to: ${formatAgentNames(targetAgents)}`);
1513
+ } else {
1514
+ spinner.start('Detecting installed agents...');
1515
+ const installedAgents = await detectInstalledAgents();
1516
+ spinner.stop(`Detected ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].green(installedAgents.length)} agent${1 !== installedAgents.length ? 's' : ''}`);
1517
+ if (0 === installedAgents.length) {
1518
+ if (skipConfirm) {
1519
+ targetAgents = allAgentTypes;
1520
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.info('Installing to all agents (none detected)');
1521
+ } else {
1522
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.warn('No coding agents detected. You can still install skills.');
1523
+ const allAgentChoices = Object.entries(agents).map(([key, config])=>({
1524
+ value: key,
1525
+ label: config.displayName
1526
+ }));
1527
+ const selected = await __WEBPACK_EXTERNAL_MODULE__clack_prompts__.multiselect({
1528
+ message: 'Select agents to install skills to',
1529
+ options: allAgentChoices,
1530
+ required: true,
1531
+ initialValues: allAgentTypes
1532
+ });
1533
+ if (__WEBPACK_EXTERNAL_MODULE__clack_prompts__.isCancel(selected)) {
1534
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.cancel('Installation cancelled');
1535
+ process.exit(0);
1536
+ }
1537
+ targetAgents = selected;
1538
+ }
1539
+ } else if (1 === installedAgents.length || skipConfirm) {
1540
+ targetAgents = installedAgents;
1541
+ if (1 === installedAgents.length) __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.info(`Installing to: ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].cyan(agents[installedAgents[0]].displayName)}`);
1542
+ else __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.info(`Installing to: ${installedAgents.map((a)=>__WEBPACK_EXTERNAL_MODULE_chalk__["default"].cyan(agents[a].displayName)).join(', ')}`);
1543
+ } else {
1544
+ const agentChoices = installedAgents.map((a)=>({
1545
+ value: a,
1546
+ label: agents[a].displayName,
1547
+ hint: agents[a].skillsDir
1548
+ }));
1549
+ const selected = await __WEBPACK_EXTERNAL_MODULE__clack_prompts__.multiselect({
1550
+ message: 'Select agents to install skills to',
1551
+ options: agentChoices,
1552
+ required: true,
1553
+ initialValues: installedAgents
1554
+ });
1555
+ if (__WEBPACK_EXTERNAL_MODULE__clack_prompts__.isCancel(selected)) {
1556
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.cancel('Installation cancelled');
1557
+ process.exit(0);
1558
+ }
1559
+ targetAgents = selected;
1560
+ }
1086
1561
  }
1087
- if (!configLoader.exists()) {
1088
- logger.error("skills.json not found. Run 'reskill init' first.");
1089
- process.exit(1);
1562
+ let installGlobally = options.global ?? false;
1563
+ if (void 0 === options.global && !skipConfirm) {
1564
+ const scope = await __WEBPACK_EXTERNAL_MODULE__clack_prompts__.select({
1565
+ message: 'Installation scope',
1566
+ options: [
1567
+ {
1568
+ value: false,
1569
+ label: 'Project',
1570
+ hint: 'Install in current directory (committed with your project)'
1571
+ },
1572
+ {
1573
+ value: true,
1574
+ label: 'Global',
1575
+ hint: 'Install in home directory (available across all projects)'
1576
+ }
1577
+ ]
1578
+ });
1579
+ if (__WEBPACK_EXTERNAL_MODULE__clack_prompts__.isCancel(scope)) {
1580
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.cancel('Installation cancelled');
1581
+ process.exit(0);
1582
+ }
1583
+ installGlobally = scope;
1090
1584
  }
1091
- const skills = configLoader.getSkills();
1092
- if (0 === Object.keys(skills).length) {
1093
- logger.info('No skills defined in skills.json');
1094
- return;
1585
+ let installMode = options.mode || 'symlink';
1586
+ if (!options.mode && !skipConfirm) {
1587
+ const modeChoice = await __WEBPACK_EXTERNAL_MODULE__clack_prompts__.select({
1588
+ message: 'Installation method',
1589
+ options: [
1590
+ {
1591
+ value: 'symlink',
1592
+ label: 'Symlink (Recommended)',
1593
+ hint: 'Single source of truth, easy updates'
1594
+ },
1595
+ {
1596
+ value: 'copy',
1597
+ label: 'Copy to all agents',
1598
+ hint: 'Independent copies for each agent'
1599
+ }
1600
+ ]
1601
+ });
1602
+ if (__WEBPACK_EXTERNAL_MODULE__clack_prompts__.isCancel(modeChoice)) {
1603
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.cancel('Installation cancelled');
1604
+ process.exit(0);
1605
+ }
1606
+ installMode = modeChoice;
1095
1607
  }
1096
- logger["package"]('Installing all skills from skills.json...');
1097
- const spinner = (0, __WEBPACK_EXTERNAL_MODULE_ora__["default"])('Installing...').start();
1098
- try {
1099
- const installed = await skillManager.installAll({
1100
- force: options.force
1608
+ const skillManager = new SkillManager(void 0, {
1609
+ global: installGlobally
1610
+ });
1611
+ const cwd = process.cwd();
1612
+ if (skill) {
1613
+ const summaryLines = [];
1614
+ summaryLines.push(`${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].cyan(skill)}`);
1615
+ summaryLines.push(` ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('→')} ${formatAgentNames(targetAgents)}`);
1616
+ summaryLines.push(` ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('Scope:')} ${installGlobally ? 'Global' : 'Project'}${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim(', Mode:')} ${installMode}`);
1617
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.note(summaryLines.join('\n'), 'Installation Summary');
1618
+ if (!skipConfirm) {
1619
+ const confirmed = await __WEBPACK_EXTERNAL_MODULE__clack_prompts__.confirm({
1620
+ message: 'Proceed with installation?'
1621
+ });
1622
+ if (__WEBPACK_EXTERNAL_MODULE__clack_prompts__.isCancel(confirmed) || !confirmed) {
1623
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.cancel('Installation cancelled');
1624
+ process.exit(0);
1625
+ }
1626
+ }
1627
+ spinner.start(`Installing ${skill}...`);
1628
+ const { skill: installed, results } = await skillManager.installToAgents(skill, targetAgents, {
1629
+ force: options.force,
1630
+ save: options.save && !installGlobally,
1631
+ mode: installMode
1101
1632
  });
1102
- spinner.stop();
1103
- logger.newline();
1104
- logger.success(`Installed ${installed.length} skill(s)`);
1105
- } catch (error) {
1106
- spinner.fail('Installation failed');
1107
- logger.error(error.message);
1108
- process.exit(1);
1633
+ spinner.stop('Installation complete');
1634
+ const successful = Array.from(results.entries()).filter(([, r])=>r.success);
1635
+ const failed = Array.from(results.entries()).filter(([, r])=>!r.success);
1636
+ const symlinkFailed = successful.filter(([, r])=>'symlink' === r.mode && r.symlinkFailed);
1637
+ if (successful.length > 0) {
1638
+ const resultLines = [];
1639
+ const firstResult = successful[0][1];
1640
+ if ('copy' === firstResult.mode) {
1641
+ resultLines.push(`${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].green('✓')} ${installed.name}@${installed.version} ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('(copied)')}`);
1642
+ for (const [, result] of successful){
1643
+ const shortPath = shortenPath(result.path, cwd);
1644
+ resultLines.push(` ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('→')} ${shortPath}`);
1645
+ }
1646
+ } else {
1647
+ if (firstResult.canonicalPath) {
1648
+ const shortPath = shortenPath(firstResult.canonicalPath, cwd);
1649
+ resultLines.push(`${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].green('✓')} ${shortPath}`);
1650
+ } else resultLines.push(`${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].green('✓')} ${installed.name}@${installed.version}`);
1651
+ const symlinked = successful.filter(([, r])=>!r.symlinkFailed).map(([a])=>agents[a].displayName);
1652
+ const copied = successful.filter(([, r])=>r.symlinkFailed).map(([a])=>agents[a].displayName);
1653
+ if (symlinked.length > 0) resultLines.push(` ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('symlink →')} ${symlinked.join(', ')}`);
1654
+ if (copied.length > 0) resultLines.push(` ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].yellow('copied →')} ${copied.join(', ')}`);
1655
+ }
1656
+ const title = __WEBPACK_EXTERNAL_MODULE_chalk__["default"].green(`Installed 1 skill to ${successful.length} agent${1 !== successful.length ? 's' : ''}`);
1657
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.note(resultLines.join('\n'), title);
1658
+ if (symlinkFailed.length > 0) {
1659
+ const copiedAgentNames = symlinkFailed.map(([a])=>agents[a].displayName);
1660
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.warn(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].yellow(`Symlinks failed for: ${copiedAgentNames.join(', ')}`));
1661
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.message(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim(' Files were copied instead. On Windows, enable Developer Mode for symlink support.'));
1662
+ }
1663
+ }
1664
+ if (failed.length > 0) {
1665
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.error(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].red(`Failed to install to ${failed.length} agent(s)`));
1666
+ for (const [agent, result] of failed)__WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.message(` ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].red('✗')} ${agents[agent].displayName}: ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim(result.error)}`);
1667
+ }
1668
+ } else {
1669
+ if (installGlobally) {
1670
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.error('Cannot install all skills globally. Please specify a skill to install.');
1671
+ process.exit(1);
1672
+ }
1673
+ if (!configLoader.exists()) {
1674
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.error("skills.json not found. Run 'reskill init' first.");
1675
+ process.exit(1);
1676
+ }
1677
+ const skills = configLoader.getSkills();
1678
+ if (0 === Object.keys(skills).length) {
1679
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.info('No skills defined in skills.json');
1680
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.outro('Done');
1681
+ return;
1682
+ }
1683
+ const summaryLines = [];
1684
+ summaryLines.push(`${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].cyan(Object.keys(skills).length)} skill(s) → ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].cyan(targetAgents.length)} agent(s)`);
1685
+ summaryLines.push(`${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim('Scope:')} ${installGlobally ? 'Global (~/)' : 'Project (./)'}${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].dim(', Mode:')} ${installMode}`);
1686
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.note(summaryLines.join('\n'), 'Installation Summary');
1687
+ if (!skipConfirm) {
1688
+ const confirmed = await __WEBPACK_EXTERNAL_MODULE__clack_prompts__.confirm({
1689
+ message: 'Proceed with installation?'
1690
+ });
1691
+ if (__WEBPACK_EXTERNAL_MODULE__clack_prompts__.isCancel(confirmed) || !confirmed) {
1692
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.cancel('Installation cancelled');
1693
+ process.exit(0);
1694
+ }
1695
+ }
1696
+ spinner.start('Installing skills...');
1697
+ let totalInstalled = 0;
1698
+ let totalFailed = 0;
1699
+ for (const [name, ref] of Object.entries(skills))try {
1700
+ const { results } = await skillManager.installToAgents(ref, targetAgents, {
1701
+ force: options.force,
1702
+ save: false,
1703
+ mode: installMode
1704
+ });
1705
+ const successCount = Array.from(results.values()).filter((r)=>r.success).length;
1706
+ totalInstalled += successCount;
1707
+ totalFailed += results.size - successCount;
1708
+ } catch (error) {
1709
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.error(`Failed to install ${name}: ${error.message}`);
1710
+ totalFailed += targetAgents.length;
1711
+ }
1712
+ spinner.stop('Installation complete');
1713
+ if (0 === totalFailed) __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.success(`Installed ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].green(Object.keys(skills).length)} skill(s) to ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].green(targetAgents.length)} agent(s)`);
1714
+ else __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.warn(`Installed ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].green(totalInstalled)} successfully, ${__WEBPACK_EXTERNAL_MODULE_chalk__["default"].red(totalFailed)} failed`);
1109
1715
  }
1716
+ console.log();
1717
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.outro(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].green('Done!'));
1718
+ } catch (error) {
1719
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.log.error(error.message);
1720
+ __WEBPACK_EXTERNAL_MODULE__clack_prompts__.outro(__WEBPACK_EXTERNAL_MODULE_chalk__["default"].red('Installation failed'));
1721
+ process.exit(1);
1110
1722
  }
1111
1723
  });
1112
1724
  const listCommand = new __WEBPACK_EXTERNAL_MODULE_commander__.Command('list').alias('ls').description('List installed skills').option('-j, --json', 'Output as JSON').option('-g, --global', 'List globally installed skills').action((options)=>{