@danieldeusing/seedr 0.1.97 → 0.1.99
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/{chunk-PEGEA2KN.js → chunk-3KPB5CCX.js} +183 -26
- package/dist/cli.js +881 -343
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -18,7 +18,7 @@ function registryDirName(config) {
|
|
|
18
18
|
}
|
|
19
19
|
return value;
|
|
20
20
|
}
|
|
21
|
-
var ALL_TYPES = ["skill", "plugin", "hook", "agent", "mcp", "settings", "command"];
|
|
21
|
+
var ALL_TYPES = ["skill", "plugin", "hook", "agent", "mcp", "settings", "command", "rule"];
|
|
22
22
|
var KNOWN_TYPES = new Set(ALL_TYPES);
|
|
23
23
|
function typeDirName(type) {
|
|
24
24
|
return type === "settings" || type === "mcp" ? type : `${type}s`;
|
|
@@ -46,6 +46,23 @@ function canonicalAgents(values) {
|
|
|
46
46
|
const present = new Set(values.map(canonicalAgent).filter((a) => a !== null));
|
|
47
47
|
return CANONICAL_AGENTS.filter((a) => present.has(a));
|
|
48
48
|
}
|
|
49
|
+
var AGENT_COMPATIBILITY = {
|
|
50
|
+
skill: ["claude", "copilot", "antigravity", "codex", "opencode"],
|
|
51
|
+
command: ["claude"],
|
|
52
|
+
// Copilot's subagent files carry the same name/description frontmatter.
|
|
53
|
+
// OpenCode's do not — theirs use `mode` and a `tools` map — so porting there
|
|
54
|
+
// needs a frontmatter translation, not a path.
|
|
55
|
+
agent: ["claude", "copilot"],
|
|
56
|
+
hook: ["claude"],
|
|
57
|
+
plugin: ["claude", "copilot", "antigravity", "codex", "opencode"],
|
|
58
|
+
settings: ["claude"],
|
|
59
|
+
mcp: ["claude", "codex", "opencode", "copilot"],
|
|
60
|
+
rule: ["claude", "copilot", "antigravity", "codex", "opencode"]
|
|
61
|
+
};
|
|
62
|
+
function isTypeSupported(type, agent) {
|
|
63
|
+
const canonical = canonicalAgent(agent);
|
|
64
|
+
return canonical !== null && AGENT_COMPATIBILITY[type].includes(canonical);
|
|
65
|
+
}
|
|
49
66
|
|
|
50
67
|
// ../registry-ops/src/sourceTypes.ts
|
|
51
68
|
var CANONICAL_SOURCE_TYPES = ["official", "seedr", "community"];
|
|
@@ -756,17 +773,35 @@ async function fetchItemToDestination(item, destPath) {
|
|
|
756
773
|
}
|
|
757
774
|
|
|
758
775
|
// src/config/agents.ts
|
|
776
|
+
import { existsSync as existsSync12 } from "fs";
|
|
759
777
|
import { homedir as homedir2 } from "os";
|
|
760
778
|
import { join as join14 } from "path";
|
|
761
779
|
var home = homedir2();
|
|
780
|
+
function claudeUserJsonPath() {
|
|
781
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR;
|
|
782
|
+
if (configDir) {
|
|
783
|
+
const scoped = join14(configDir, ".config.json");
|
|
784
|
+
if (existsSync12(scoped)) return scoped;
|
|
785
|
+
}
|
|
786
|
+
return join14(configDir || home, ".claude.json");
|
|
787
|
+
}
|
|
788
|
+
var copilotUserRoot = () => process.env.COPILOT_HOME || join14(home, ".copilot");
|
|
789
|
+
var codexUserRoot = () => process.env.CODEX_HOME || join14(home, ".codex");
|
|
790
|
+
var openCodeUserConfigDir = () => process.env.OPENCODE_CONFIG_DIR || (process.env.XDG_CONFIG_HOME ? join14(process.env.XDG_CONFIG_HOME, "opencode") : join14(home, ".config", "opencode"));
|
|
791
|
+
var claudeUserRoot = () => process.env.CLAUDE_CONFIG_DIR || join14(home, ".claude");
|
|
762
792
|
var SKILL_DIRECTORY = {
|
|
763
793
|
path: "skills"
|
|
764
794
|
};
|
|
765
795
|
var ANTIGRAVITY = {
|
|
766
796
|
name: "Google Antigravity",
|
|
767
797
|
shortName: "antigravity",
|
|
798
|
+
// Project content is the agent-neutral `.agents/` tree, which IS Antigravity's
|
|
799
|
+
// own project root. The personal tier is not the same spelling: the shipped
|
|
800
|
+
// CLI reads `~/.gemini/config/skills`, and the vendor documentation states
|
|
801
|
+
// outright that `~/.agents` does not exist for it. `~/.gemini/skills` is the
|
|
802
|
+
// predecessor Gemini CLI location and is not written.
|
|
768
803
|
projectRoot: ".agents",
|
|
769
|
-
userRoot: join14(home, ".
|
|
804
|
+
userRoot: join14(home, ".gemini", "config"),
|
|
770
805
|
contentTypes: { skill: SKILL_DIRECTORY }
|
|
771
806
|
};
|
|
772
807
|
var CODING_AGENTS = {
|
|
@@ -774,7 +809,7 @@ var CODING_AGENTS = {
|
|
|
774
809
|
name: "Claude Code",
|
|
775
810
|
shortName: "claude",
|
|
776
811
|
projectRoot: ".claude",
|
|
777
|
-
userRoot:
|
|
812
|
+
userRoot: claudeUserRoot(),
|
|
778
813
|
contentTypes: {
|
|
779
814
|
skill: SKILL_DIRECTORY,
|
|
780
815
|
command: {
|
|
@@ -800,9 +835,15 @@ var CODING_AGENTS = {
|
|
|
800
835
|
copilot: {
|
|
801
836
|
name: "GitHub Copilot",
|
|
802
837
|
shortName: "copilot",
|
|
838
|
+
// Project content is `.github/`, but the personal tier is `~/.copilot/` —
|
|
839
|
+
// the two are not the same spelling. `~/.github/skills` is read by nothing;
|
|
840
|
+
// `~/.copilot/skills` is what the CLI itself populates.
|
|
803
841
|
projectRoot: ".github",
|
|
804
|
-
userRoot:
|
|
805
|
-
|
|
842
|
+
userRoot: copilotUserRoot(),
|
|
843
|
+
// Subagents are `<name>.agent.md` under `agents/`, with the same
|
|
844
|
+
// `name` + `description` frontmatter a Claude subagent carries — confirmed
|
|
845
|
+
// from files on a real machine.
|
|
846
|
+
contentTypes: { skill: SKILL_DIRECTORY, agent: { path: "agents" } }
|
|
806
847
|
},
|
|
807
848
|
antigravity: ANTIGRAVITY,
|
|
808
849
|
gemini: ANTIGRAVITY,
|
|
@@ -810,14 +851,19 @@ var CODING_AGENTS = {
|
|
|
810
851
|
name: "OpenAI Codex CLI",
|
|
811
852
|
shortName: "codex",
|
|
812
853
|
projectRoot: ".codex",
|
|
813
|
-
userRoot:
|
|
854
|
+
userRoot: codexUserRoot(),
|
|
814
855
|
contentTypes: { skill: SKILL_DIRECTORY }
|
|
815
856
|
},
|
|
816
857
|
opencode: {
|
|
817
858
|
name: "OpenCode",
|
|
818
859
|
shortName: "opencode",
|
|
860
|
+
// `~/.opencode` is the LEGACY user directory. The global config directory
|
|
861
|
+
// is `~/.config/opencode`, which is where this package already writes
|
|
862
|
+
// `opencode.json` and `AGENTS.md` — splitting one agent across two roots
|
|
863
|
+
// made `list` and `remove` diverge, and creating `~/.opencode` on a machine
|
|
864
|
+
// that had none adds a capability directory ranked above every project one.
|
|
819
865
|
projectRoot: ".opencode",
|
|
820
|
-
userRoot:
|
|
866
|
+
userRoot: openCodeUserConfigDir(),
|
|
821
867
|
contentTypes: { skill: SKILL_DIRECTORY }
|
|
822
868
|
}
|
|
823
869
|
};
|
|
@@ -849,7 +895,7 @@ function getSettingsPath(scope, cwd = process.cwd()) {
|
|
|
849
895
|
case "project":
|
|
850
896
|
return join14(cwd, ".claude/settings.json");
|
|
851
897
|
case "user":
|
|
852
|
-
return join14(
|
|
898
|
+
return join14(claudeUserRoot(), "settings.json");
|
|
853
899
|
case "local":
|
|
854
900
|
return join14(cwd, ".claude/settings.local.json");
|
|
855
901
|
}
|
|
@@ -858,11 +904,13 @@ function getMcpConfigPath(agent, scope, cwd = process.cwd()) {
|
|
|
858
904
|
const isUser = scope === "user";
|
|
859
905
|
switch (canonicalAgent(agent) ?? agent) {
|
|
860
906
|
case "claude":
|
|
861
|
-
return isUser ?
|
|
907
|
+
return isUser ? claudeUserJsonPath() : join14(cwd, ".mcp.json");
|
|
862
908
|
case "codex":
|
|
863
|
-
return isUser ? join14(
|
|
909
|
+
return isUser ? join14(codexUserRoot(), "config.toml") : join14(cwd, ".codex", "config.toml");
|
|
864
910
|
case "opencode":
|
|
865
|
-
return isUser ? join14(
|
|
911
|
+
return isUser ? join14(openCodeUserConfigDir(), "opencode.json") : join14(cwd, "opencode.json");
|
|
912
|
+
case "copilot":
|
|
913
|
+
return isUser ? join14(copilotUserRoot(), "mcp-config.json") : join14(cwd, ".mcp.json");
|
|
866
914
|
default:
|
|
867
915
|
throw new Error(`${agent} has no verified MCP configuration format`);
|
|
868
916
|
}
|
|
@@ -1041,18 +1089,94 @@ function error(message) {
|
|
|
1041
1089
|
}
|
|
1042
1090
|
|
|
1043
1091
|
// src/handlers/skill.ts
|
|
1044
|
-
import { relative as relative5, dirname as
|
|
1092
|
+
import { relative as relative5, dirname as dirname8, join as join15 } from "path";
|
|
1045
1093
|
import { homedir as homedir3 } from "os";
|
|
1046
1094
|
import { readdir as readdir2, symlink as symlink2 } from "fs/promises";
|
|
1047
1095
|
import chalk2 from "chalk";
|
|
1048
1096
|
import ora from "ora";
|
|
1097
|
+
|
|
1098
|
+
// src/utils/json.ts
|
|
1099
|
+
import { readFile as readFile4, stat as stat2 } from "fs/promises";
|
|
1100
|
+
import { dirname as dirname7 } from "path";
|
|
1101
|
+
async function readJson(path) {
|
|
1102
|
+
try {
|
|
1103
|
+
const content = await readFile4(path, "utf-8");
|
|
1104
|
+
return JSON.parse(content);
|
|
1105
|
+
} catch (error2) {
|
|
1106
|
+
if (error2.code === "ENOENT") {
|
|
1107
|
+
return {};
|
|
1108
|
+
}
|
|
1109
|
+
if (error2 instanceof SyntaxError) {
|
|
1110
|
+
throw new Error(`${path} is not valid JSON: ${error2.message}`, { cause: error2 });
|
|
1111
|
+
}
|
|
1112
|
+
throw error2;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
async function existingFileMode(path) {
|
|
1116
|
+
try {
|
|
1117
|
+
return (await stat2(path)).mode & 511;
|
|
1118
|
+
} catch (error2) {
|
|
1119
|
+
if (error2.code === "ENOENT") return void 0;
|
|
1120
|
+
throw error2;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
async function writeJson(path, data) {
|
|
1124
|
+
await ensureDir(dirname7(path));
|
|
1125
|
+
const mode = await existingFileMode(path);
|
|
1126
|
+
await writeFileAtomic(path, JSON.stringify(data, null, 2) + "\n", { mode });
|
|
1127
|
+
}
|
|
1128
|
+
function deepMerge(target, source) {
|
|
1129
|
+
const result = { ...target };
|
|
1130
|
+
for (const key of Object.keys(source)) {
|
|
1131
|
+
const sourceValue = source[key];
|
|
1132
|
+
const targetValue = result[key];
|
|
1133
|
+
if (sourceValue !== null && typeof sourceValue === "object" && !Array.isArray(sourceValue) && targetValue !== null && typeof targetValue === "object" && !Array.isArray(targetValue)) {
|
|
1134
|
+
result[key] = deepMerge(
|
|
1135
|
+
targetValue,
|
|
1136
|
+
sourceValue
|
|
1137
|
+
);
|
|
1138
|
+
} else if (sourceValue !== void 0) {
|
|
1139
|
+
result[key] = sourceValue;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
return result;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
// src/handlers/skill.ts
|
|
1049
1146
|
var SLUG_LABEL = "skill slug";
|
|
1050
|
-
|
|
1147
|
+
function readsCentralDir(agent, scope) {
|
|
1148
|
+
const canonical = canonicalAgent(agent) ?? agent;
|
|
1149
|
+
if (canonical === "antigravity") return scope !== "user";
|
|
1150
|
+
return canonical === "codex" || canonical === "opencode";
|
|
1151
|
+
}
|
|
1152
|
+
var OWNERS_FILE = ".seedr-central-owners.json";
|
|
1153
|
+
async function readOwners(scope, cwd) {
|
|
1154
|
+
return readJson(join15(centralSkillsDir(scope, cwd), OWNERS_FILE));
|
|
1155
|
+
}
|
|
1156
|
+
async function writeOwners(owners, scope, cwd) {
|
|
1157
|
+
await writeJson(join15(centralSkillsDir(scope, cwd), OWNERS_FILE), owners);
|
|
1158
|
+
}
|
|
1159
|
+
async function addOwners(slug, agents, scope, cwd) {
|
|
1160
|
+
if (agents.length === 0) return;
|
|
1161
|
+
const owners = await readOwners(scope, cwd);
|
|
1162
|
+
owners[slug] = [.../* @__PURE__ */ new Set([...owners[slug] ?? [], ...agents])];
|
|
1163
|
+
await writeOwners(owners, scope, cwd);
|
|
1164
|
+
}
|
|
1165
|
+
async function dropOwner(slug, agent, scope, cwd) {
|
|
1166
|
+
const owners = await readOwners(scope, cwd);
|
|
1167
|
+
const recorded = owners[slug];
|
|
1168
|
+
if (!recorded) return [];
|
|
1169
|
+
const remaining = recorded.filter((owner) => owner !== (canonicalAgent(agent) ?? agent));
|
|
1170
|
+
if (remaining.length > 0) owners[slug] = remaining;
|
|
1171
|
+
else delete owners[slug];
|
|
1172
|
+
await writeOwners(owners, scope, cwd);
|
|
1173
|
+
return remaining;
|
|
1174
|
+
}
|
|
1051
1175
|
function getScopeRoot(scope, cwd) {
|
|
1052
1176
|
return scope === "user" ? homedir3() : cwd;
|
|
1053
1177
|
}
|
|
1054
1178
|
function centralSkillsDir(scope, cwd) {
|
|
1055
|
-
return
|
|
1179
|
+
return dirname8(getAgentsPath("skill", "any-slug", scope, cwd));
|
|
1056
1180
|
}
|
|
1057
1181
|
async function resolveCentralPath(slug, scope, cwd) {
|
|
1058
1182
|
const scopeRoot = getScopeRoot(scope, cwd);
|
|
@@ -1077,9 +1201,9 @@ async function installToCentralLocation(item, sourcePath, scope, force, cwd) {
|
|
|
1077
1201
|
return { centralPath, created: !existed };
|
|
1078
1202
|
}
|
|
1079
1203
|
async function createAgentSymlink(centralPath, destPath) {
|
|
1080
|
-
await ensureDir(
|
|
1204
|
+
await ensureDir(dirname8(destPath));
|
|
1081
1205
|
await removePathEntry(destPath);
|
|
1082
|
-
const relPath = relative5(
|
|
1206
|
+
const relPath = relative5(dirname8(destPath), centralPath);
|
|
1083
1207
|
await symlink2(relPath, destPath);
|
|
1084
1208
|
}
|
|
1085
1209
|
async function installSkillForAgent(item, agent, scope, method, force, cwd, centralPath) {
|
|
@@ -1121,7 +1245,7 @@ async function installSkill(item, agents, scope, method, force, cwd = process.cw
|
|
|
1121
1245
|
central = await installToCentralLocation(item, sourcePath, scope, force, cwd);
|
|
1122
1246
|
}
|
|
1123
1247
|
for (const agent of agents) {
|
|
1124
|
-
if (
|
|
1248
|
+
if (readsCentralDir(agent, scope) && central) {
|
|
1125
1249
|
results.push({ agent, success: true, path: central.centralPath });
|
|
1126
1250
|
continue;
|
|
1127
1251
|
}
|
|
@@ -1138,15 +1262,30 @@ async function installSkill(item, agents, scope, method, force, cwd = process.cw
|
|
|
1138
1262
|
}
|
|
1139
1263
|
if (central?.created && !results.some((result) => result.success)) {
|
|
1140
1264
|
await removePathEntry(central.centralPath);
|
|
1265
|
+
return results;
|
|
1266
|
+
}
|
|
1267
|
+
if (central) {
|
|
1268
|
+
const centralReaders = agents.filter(
|
|
1269
|
+
(agent) => readsCentralDir(agent, scope) && results.some((result) => result.agent === agent && result.success)
|
|
1270
|
+
);
|
|
1271
|
+
await addOwners(item.slug, centralReaders, scope, cwd);
|
|
1141
1272
|
}
|
|
1142
1273
|
return results;
|
|
1143
1274
|
}
|
|
1144
1275
|
async function uninstallSkill(slug, agent, scope, cwd = process.cwd()) {
|
|
1145
1276
|
assertValidSlug(slug, SLUG_LABEL);
|
|
1277
|
+
const central = await resolveCentralPath(slug, scope, cwd);
|
|
1146
1278
|
const destPath = await resolveAgentSkillPath(agent, slug, scope, cwd);
|
|
1147
|
-
if (
|
|
1148
|
-
|
|
1149
|
-
|
|
1279
|
+
if (readsCentralDir(agent, scope) || destPath === central) {
|
|
1280
|
+
const remaining = await dropOwner(slug, agent, scope, cwd);
|
|
1281
|
+
if (remaining.length > 0) {
|
|
1282
|
+
return true;
|
|
1283
|
+
}
|
|
1284
|
+
return removePathEntry(central);
|
|
1285
|
+
}
|
|
1286
|
+
if (destPath && await removePathEntry(destPath)) {
|
|
1287
|
+
await dropOwner(slug, agent, scope, cwd);
|
|
1288
|
+
return true;
|
|
1150
1289
|
}
|
|
1151
1290
|
return false;
|
|
1152
1291
|
}
|
|
@@ -1154,13 +1293,21 @@ async function getInstalledSkills(agent, scope, cwd = process.cwd()) {
|
|
|
1154
1293
|
const dirs = /* @__PURE__ */ new Set();
|
|
1155
1294
|
const own = getContentPath(agent, "skill", scope, cwd);
|
|
1156
1295
|
if (own) dirs.add(own);
|
|
1157
|
-
if (
|
|
1296
|
+
if (readsCentralDir(agent, scope)) dirs.add(centralSkillsDir(scope, cwd));
|
|
1297
|
+
const owners = await readOwners(scope, cwd);
|
|
1298
|
+
const centralDir = centralSkillsDir(scope, cwd);
|
|
1299
|
+
const canonical = canonicalAgent(agent) ?? agent;
|
|
1300
|
+
const isInstalledHere = (entry, dir) => {
|
|
1301
|
+
if (entry.name.startsWith(".")) return false;
|
|
1302
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink()) return false;
|
|
1303
|
+
const recorded = dir === centralDir ? owners[entry.name] : void 0;
|
|
1304
|
+
return !recorded || recorded.includes(canonical);
|
|
1305
|
+
};
|
|
1158
1306
|
const slugs = /* @__PURE__ */ new Set();
|
|
1159
1307
|
for (const dir of dirs) {
|
|
1160
1308
|
if (!await exists(dir)) continue;
|
|
1161
|
-
const
|
|
1162
|
-
|
|
1163
|
-
if ((entry.isDirectory() || entry.isSymbolicLink()) && !entry.name.startsWith(".")) slugs.add(entry.name);
|
|
1309
|
+
for (const entry of await readdir2(dir, { withFileTypes: true })) {
|
|
1310
|
+
if (isInstalledHere(entry, dir)) slugs.add(entry.name);
|
|
1164
1311
|
}
|
|
1165
1312
|
}
|
|
1166
1313
|
return [...slugs];
|
|
@@ -1172,7 +1319,7 @@ async function planSkill(item, agents, scope, method, cwd) {
|
|
|
1172
1319
|
let centralPath;
|
|
1173
1320
|
if (method === "symlink") {
|
|
1174
1321
|
centralPath = await resolveCentralPath(item.slug, scope, cwd);
|
|
1175
|
-
const sharedBy = agents.filter((agent) =>
|
|
1322
|
+
const sharedBy = agents.filter((agent) => readsCentralDir(agent, scope));
|
|
1176
1323
|
changes.push({
|
|
1177
1324
|
agent: "shared",
|
|
1178
1325
|
kind: await kindFor(centralPath),
|
|
@@ -1181,7 +1328,7 @@ async function planSkill(item, agents, scope, method, cwd) {
|
|
|
1181
1328
|
});
|
|
1182
1329
|
}
|
|
1183
1330
|
for (const agent of agents) {
|
|
1184
|
-
if (centralPath &&
|
|
1331
|
+
if (centralPath && readsCentralDir(agent, scope)) continue;
|
|
1185
1332
|
const destPath = await resolveAgentSkillPath(agent, item.slug, scope, cwd);
|
|
1186
1333
|
if (!destPath) throw new Error(`${CODING_AGENTS[agent].name} does not support skills`);
|
|
1187
1334
|
changes.push({
|
|
@@ -1208,10 +1355,13 @@ var skillHandler = {
|
|
|
1208
1355
|
};
|
|
1209
1356
|
|
|
1210
1357
|
export {
|
|
1358
|
+
ALL_TYPES,
|
|
1211
1359
|
mainFileName,
|
|
1212
1360
|
isLegacyAgent,
|
|
1213
1361
|
canonicalAgent,
|
|
1214
1362
|
canonicalAgents,
|
|
1363
|
+
AGENT_COMPATIBILITY,
|
|
1364
|
+
isTypeSupported,
|
|
1215
1365
|
SLUG_PATTERN2 as SLUG_PATTERN,
|
|
1216
1366
|
MAX_SLUG_LENGTH2 as MAX_SLUG_LENGTH,
|
|
1217
1367
|
isValidSlug2 as isValidSlug,
|
|
@@ -1242,6 +1392,10 @@ export {
|
|
|
1242
1392
|
fetchItemFile,
|
|
1243
1393
|
getItemSourcePath,
|
|
1244
1394
|
fetchItemToDestination,
|
|
1395
|
+
copilotUserRoot,
|
|
1396
|
+
codexUserRoot,
|
|
1397
|
+
openCodeUserConfigDir,
|
|
1398
|
+
claudeUserRoot,
|
|
1245
1399
|
CODING_AGENTS,
|
|
1246
1400
|
ALL_AGENTS,
|
|
1247
1401
|
getAgentConfig,
|
|
@@ -1269,6 +1423,9 @@ export {
|
|
|
1269
1423
|
success,
|
|
1270
1424
|
warn,
|
|
1271
1425
|
error,
|
|
1426
|
+
readJson,
|
|
1427
|
+
writeJson,
|
|
1428
|
+
deepMerge,
|
|
1272
1429
|
installSkill,
|
|
1273
1430
|
uninstallSkill,
|
|
1274
1431
|
getInstalledSkills,
|