@danieldeusing/seedr 0.1.129 → 0.1.131
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/README.md +2 -2
- package/dist/{chunk-USS5HTCG.js → chunk-7RMRI2TO.js} +6 -22
- package/dist/cli.js +184 -85
- package/dist/index.d.ts +8 -4
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @danieldeusing/seedr
|
|
2
2
|
|
|
3
3
|
Seed your coding agents with capabilities: install curated skills, agents, hooks, plugins,
|
|
4
|
-
MCP servers and settings presets for Claude Code, GitHub Copilot,
|
|
5
|
-
OpenCode with one command.
|
|
4
|
+
MCP servers and settings presets for Claude Code, GitHub Copilot, Google Antigravity, OpenAI
|
|
5
|
+
Codex and OpenCode with one command.
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npx @danieldeusing/seedr add # interactive picker
|
|
@@ -29,18 +29,11 @@ function mainFileName(type) {
|
|
|
29
29
|
|
|
30
30
|
// ../registry-ops/src/agents.ts
|
|
31
31
|
var CANONICAL_AGENTS = ["claude", "copilot", "antigravity", "codex", "opencode"];
|
|
32
|
-
var AGENT_ALIASES = { gemini: "antigravity" };
|
|
33
|
-
var KNOWN_AGENTS = [...CANONICAL_AGENTS, ...Object.keys(AGENT_ALIASES)];
|
|
34
32
|
function isCanonicalAgent(value) {
|
|
35
33
|
return typeof value === "string" && CANONICAL_AGENTS.includes(value);
|
|
36
34
|
}
|
|
37
|
-
function isLegacyAgent(value) {
|
|
38
|
-
return typeof value === "string" && Object.hasOwn(AGENT_ALIASES, value);
|
|
39
|
-
}
|
|
40
35
|
function canonicalAgent(value) {
|
|
41
|
-
|
|
42
|
-
if (isLegacyAgent(value)) return AGENT_ALIASES[value];
|
|
43
|
-
return null;
|
|
36
|
+
return isCanonicalAgent(value) ? value : null;
|
|
44
37
|
}
|
|
45
38
|
function canonicalAgents(values) {
|
|
46
39
|
const present = new Set(values.map(canonicalAgent).filter((a) => a !== null));
|
|
@@ -157,9 +150,6 @@ import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as re
|
|
|
157
150
|
import { dirname as dirname4, join as join10, relative as relative3, resolve as resolve2 } from "path";
|
|
158
151
|
var DEFAULT_LOCK_STALE_MS = 10 * 60 * 1e3;
|
|
159
152
|
|
|
160
|
-
// ../registry-ops/src/migrate.ts
|
|
161
|
-
import { writeFileSync as writeFileSync9 } from "fs";
|
|
162
|
-
|
|
163
153
|
// src/utils/slug.ts
|
|
164
154
|
var SLUG_PATTERN2 = /^[a-z0-9][a-z0-9-]*$/;
|
|
165
155
|
var MAX_SLUG_LENGTH2 = 100;
|
|
@@ -846,7 +836,6 @@ var CODING_AGENTS = {
|
|
|
846
836
|
contentTypes: { skill: SKILL_DIRECTORY, agent: { path: "agents" } }
|
|
847
837
|
},
|
|
848
838
|
antigravity: ANTIGRAVITY,
|
|
849
|
-
gemini: ANTIGRAVITY,
|
|
850
839
|
codex: {
|
|
851
840
|
name: "OpenAI Codex CLI",
|
|
852
841
|
shortName: "codex",
|
|
@@ -902,7 +891,7 @@ function getSettingsPath(scope, cwd = process.cwd()) {
|
|
|
902
891
|
}
|
|
903
892
|
function getMcpConfigPath(agent, scope, cwd = process.cwd()) {
|
|
904
893
|
const isUser = scope === "user";
|
|
905
|
-
switch (
|
|
894
|
+
switch (agent) {
|
|
906
895
|
case "claude":
|
|
907
896
|
return isUser ? claudeUserJsonPath() : join14(cwd, ".mcp.json");
|
|
908
897
|
case "codex":
|
|
@@ -955,8 +944,6 @@ function parseAgentArg(arg) {
|
|
|
955
944
|
gh: "copilot",
|
|
956
945
|
"google-antigravity": "antigravity",
|
|
957
946
|
agy: "antigravity",
|
|
958
|
-
"gemini-code": "antigravity",
|
|
959
|
-
gca: "antigravity",
|
|
960
947
|
"openai-codex": "codex",
|
|
961
948
|
oc: "opencode"
|
|
962
949
|
};
|
|
@@ -1145,9 +1132,8 @@ function deepMerge(target, source) {
|
|
|
1145
1132
|
// src/handlers/skill.ts
|
|
1146
1133
|
var SLUG_LABEL = "skill slug";
|
|
1147
1134
|
function readsCentralDir(agent, scope) {
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
return canonical === "codex" || canonical === "opencode";
|
|
1135
|
+
if (agent === "antigravity") return scope !== "user";
|
|
1136
|
+
return agent === "codex" || agent === "opencode";
|
|
1151
1137
|
}
|
|
1152
1138
|
var OWNERS_FILE = ".seedr-central-owners.json";
|
|
1153
1139
|
async function readOwners(scope, cwd) {
|
|
@@ -1166,7 +1152,7 @@ async function dropOwner(slug, agent, scope, cwd) {
|
|
|
1166
1152
|
const owners = await readOwners(scope, cwd);
|
|
1167
1153
|
const recorded = owners[slug];
|
|
1168
1154
|
if (!recorded) return [];
|
|
1169
|
-
const remaining = recorded.filter((owner) => owner !==
|
|
1155
|
+
const remaining = recorded.filter((owner) => owner !== agent);
|
|
1170
1156
|
if (remaining.length > 0) owners[slug] = remaining;
|
|
1171
1157
|
else delete owners[slug];
|
|
1172
1158
|
await writeOwners(owners, scope, cwd);
|
|
@@ -1296,12 +1282,11 @@ async function getInstalledSkills(agent, scope, cwd = process.cwd()) {
|
|
|
1296
1282
|
if (readsCentralDir(agent, scope)) dirs.add(centralSkillsDir(scope, cwd));
|
|
1297
1283
|
const owners = await readOwners(scope, cwd);
|
|
1298
1284
|
const centralDir = centralSkillsDir(scope, cwd);
|
|
1299
|
-
const canonical = canonicalAgent(agent) ?? agent;
|
|
1300
1285
|
const isInstalledHere = (entry, dir) => {
|
|
1301
1286
|
if (entry.name.startsWith(".")) return false;
|
|
1302
1287
|
if (!entry.isDirectory() && !entry.isSymbolicLink()) return false;
|
|
1303
1288
|
const recorded = dir === centralDir ? owners[entry.name] : void 0;
|
|
1304
|
-
return !recorded || recorded.includes(
|
|
1289
|
+
return !recorded || recorded.includes(agent);
|
|
1305
1290
|
};
|
|
1306
1291
|
const slugs = /* @__PURE__ */ new Set();
|
|
1307
1292
|
for (const dir of dirs) {
|
|
@@ -1357,7 +1342,6 @@ var skillHandler = {
|
|
|
1357
1342
|
export {
|
|
1358
1343
|
ALL_TYPES,
|
|
1359
1344
|
mainFileName,
|
|
1360
|
-
isLegacyAgent,
|
|
1361
1345
|
canonicalAgent,
|
|
1362
1346
|
canonicalAgents,
|
|
1363
1347
|
AGENT_COMPATIBILITY,
|
package/dist/cli.js
CHANGED
|
@@ -39,7 +39,6 @@ import {
|
|
|
39
39
|
intro,
|
|
40
40
|
isFirstParty,
|
|
41
41
|
isInteractive,
|
|
42
|
-
isLegacyAgent,
|
|
43
42
|
isTypeSupported,
|
|
44
43
|
isValidSlug,
|
|
45
44
|
listItems,
|
|
@@ -68,7 +67,7 @@ import {
|
|
|
68
67
|
writeFileAtomic,
|
|
69
68
|
writeJson,
|
|
70
69
|
writeTextFile
|
|
71
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-7RMRI2TO.js";
|
|
72
71
|
|
|
73
72
|
// src/cli.ts
|
|
74
73
|
import { Command as Command5 } from "commander";
|
|
@@ -148,7 +147,7 @@ function isTelemetryDisabled(env = process.env) {
|
|
|
148
147
|
return env[TELEMETRY_OPT_OUT_VARIABLE] !== void 0;
|
|
149
148
|
}
|
|
150
149
|
function cliVersion() {
|
|
151
|
-
return true ? "0.1.
|
|
150
|
+
return true ? "0.1.131" : "dev";
|
|
152
151
|
}
|
|
153
152
|
async function sendEvent(event) {
|
|
154
153
|
try {
|
|
@@ -168,6 +167,36 @@ function trackInstalls(slug, type, results, scope) {
|
|
|
168
167
|
return Promise.all(sends).then(() => void 0);
|
|
169
168
|
}
|
|
170
169
|
|
|
170
|
+
// src/utils/ledger.ts
|
|
171
|
+
import { homedir } from "os";
|
|
172
|
+
import { join } from "path";
|
|
173
|
+
var LEDGER_PATH = join(homedir(), ".seedr", "installed.json");
|
|
174
|
+
function ledgerKey(type, slug) {
|
|
175
|
+
return `${type}:${slug}`;
|
|
176
|
+
}
|
|
177
|
+
async function readLedger() {
|
|
178
|
+
const ledger = await readJson(LEDGER_PATH);
|
|
179
|
+
return { version: 1, items: ledger.items ?? {} };
|
|
180
|
+
}
|
|
181
|
+
async function recordInstall(entry) {
|
|
182
|
+
const ledger = await readLedger();
|
|
183
|
+
const key = ledgerKey(entry.type, entry.slug);
|
|
184
|
+
const previous = ledger.items[key];
|
|
185
|
+
const agents = previous && previous.version === entry.version ? [.../* @__PURE__ */ new Set([...previous.agents, ...entry.agents])].sort() : [...entry.agents].sort();
|
|
186
|
+
ledger.items[key] = { ...entry, agents };
|
|
187
|
+
await writeJson(LEDGER_PATH, ledger);
|
|
188
|
+
}
|
|
189
|
+
async function recordRemoval(type, slug, agents) {
|
|
190
|
+
const ledger = await readLedger();
|
|
191
|
+
const key = ledgerKey(type, slug);
|
|
192
|
+
const entry = ledger.items[key];
|
|
193
|
+
if (!entry) return;
|
|
194
|
+
const left = entry.agents.filter((agent) => !agents.includes(agent));
|
|
195
|
+
if (left.length === 0) delete ledger.items[key];
|
|
196
|
+
else ledger.items[key] = { ...entry, agents: left };
|
|
197
|
+
await writeJson(LEDGER_PATH, ledger);
|
|
198
|
+
}
|
|
199
|
+
|
|
171
200
|
// src/config/compatibility.ts
|
|
172
201
|
function filterCompatibleAgents(type, agents) {
|
|
173
202
|
const compatible = AGENT_COMPATIBILITY[type];
|
|
@@ -185,19 +214,19 @@ function describeIncompatibility(type, agent) {
|
|
|
185
214
|
}
|
|
186
215
|
|
|
187
216
|
// src/handlers/agent.ts
|
|
188
|
-
import { join, relative } from "path";
|
|
189
|
-
import { homedir } from "os";
|
|
217
|
+
import { join as join2, relative } from "path";
|
|
218
|
+
import { homedir as homedir2 } from "os";
|
|
190
219
|
import { lstat, readdir, unlink } from "fs/promises";
|
|
191
220
|
import chalk2 from "chalk";
|
|
192
221
|
import ora from "ora";
|
|
193
222
|
var SLUG_LABEL = "agent slug";
|
|
194
223
|
function subagentFileName(agent, slug) {
|
|
195
|
-
return
|
|
224
|
+
return agent === "copilot" ? `${slug}.agent.md` : `${slug}.md`;
|
|
196
225
|
}
|
|
197
226
|
async function resolveAgentFilePath(agent, slug, scope, cwd) {
|
|
198
227
|
const destDir = getContentPath(agent, "agent", scope, cwd);
|
|
199
228
|
if (!destDir) return null;
|
|
200
|
-
const scopeRoot = scope === "user" ?
|
|
229
|
+
const scopeRoot = scope === "user" ? homedir2() : cwd;
|
|
201
230
|
return resolveContained(scopeRoot, relative(scopeRoot, destDir), subagentFileName(agent, slug));
|
|
202
231
|
}
|
|
203
232
|
async function installAgentForCodingAgent(item, agent, scope, method, force, cwd) {
|
|
@@ -212,7 +241,7 @@ async function installAgentForCodingAgent(item, agent, scope, method, force, cwd
|
|
|
212
241
|
}
|
|
213
242
|
await assertOverwritable(destPath, force);
|
|
214
243
|
const sourcePath = getItemSourcePath(item);
|
|
215
|
-
const sourceFile = sourcePath ?
|
|
244
|
+
const sourceFile = sourcePath ? join2(sourcePath, mainFileName("agent")) : null;
|
|
216
245
|
if (method === "symlink" && sourceFile && await exists(sourceFile)) {
|
|
217
246
|
await installFile(sourceFile, destPath, "symlink");
|
|
218
247
|
} else {
|
|
@@ -273,12 +302,12 @@ async function planAgent(item, agents, scope, method, cwd) {
|
|
|
273
302
|
const destPath = await resolveAgentFilePath(agent, item.slug, scope, cwd);
|
|
274
303
|
if (!destPath) throw new Error(`${CODING_AGENTS[agent].name} does not support agents`);
|
|
275
304
|
const sourcePath = getItemSourcePath(item);
|
|
276
|
-
const linked = method === "symlink" && sourcePath !== null && await exists(
|
|
305
|
+
const linked = method === "symlink" && sourcePath !== null && await exists(join2(sourcePath, mainFileName("agent")));
|
|
277
306
|
changes.push({
|
|
278
307
|
agent,
|
|
279
308
|
kind: await exists(destPath) ? "modify" : "create",
|
|
280
309
|
path: destPath,
|
|
281
|
-
detail: linked ? `symlink \u2192 ${
|
|
310
|
+
detail: linked ? `symlink \u2192 ${join2(sourcePath, mainFileName("agent"))}` : "agent definition file"
|
|
282
311
|
});
|
|
283
312
|
}
|
|
284
313
|
return changes;
|
|
@@ -298,8 +327,8 @@ var agentHandler = {
|
|
|
298
327
|
};
|
|
299
328
|
|
|
300
329
|
// src/handlers/command.ts
|
|
301
|
-
import { join as
|
|
302
|
-
import { homedir as
|
|
330
|
+
import { join as join3, relative as relative2 } from "path";
|
|
331
|
+
import { homedir as homedir3 } from "os";
|
|
303
332
|
import { lstat as lstat2, readdir as readdir2, unlink as unlink2 } from "fs/promises";
|
|
304
333
|
import chalk3 from "chalk";
|
|
305
334
|
import ora2 from "ora";
|
|
@@ -307,7 +336,7 @@ var SLUG_LABEL2 = "command slug";
|
|
|
307
336
|
async function resolveCommandFilePath(agent, slug, scope, cwd) {
|
|
308
337
|
const destDir = getContentPath(agent, "command", scope, cwd);
|
|
309
338
|
if (!destDir) return null;
|
|
310
|
-
const scopeRoot = scope === "user" ?
|
|
339
|
+
const scopeRoot = scope === "user" ? homedir3() : cwd;
|
|
311
340
|
return resolveContained(scopeRoot, relative2(scopeRoot, destDir), `${slug}.md`);
|
|
312
341
|
}
|
|
313
342
|
async function installCommandForCodingAgent(item, agent, scope, method, force, cwd) {
|
|
@@ -322,7 +351,7 @@ async function installCommandForCodingAgent(item, agent, scope, method, force, c
|
|
|
322
351
|
}
|
|
323
352
|
await assertOverwritable(destPath, force);
|
|
324
353
|
const sourcePath = getItemSourcePath(item);
|
|
325
|
-
const sourceFile = sourcePath ?
|
|
354
|
+
const sourceFile = sourcePath ? join3(sourcePath, mainFileName("command")) : null;
|
|
326
355
|
if (method === "symlink" && sourceFile && await exists(sourceFile)) {
|
|
327
356
|
await installFile(sourceFile, destPath, "symlink");
|
|
328
357
|
} else {
|
|
@@ -382,12 +411,12 @@ async function planCommand(item, agents, scope, method, cwd) {
|
|
|
382
411
|
const destPath = await resolveCommandFilePath(agent, item.slug, scope, cwd);
|
|
383
412
|
if (!destPath) throw new Error(`${CODING_AGENTS[agent].name} does not support commands`);
|
|
384
413
|
const sourcePath = getItemSourcePath(item);
|
|
385
|
-
const linked = method === "symlink" && sourcePath !== null && await exists(
|
|
414
|
+
const linked = method === "symlink" && sourcePath !== null && await exists(join3(sourcePath, mainFileName("command")));
|
|
386
415
|
changes.push({
|
|
387
416
|
agent,
|
|
388
417
|
kind: await exists(destPath) ? "modify" : "create",
|
|
389
418
|
path: destPath,
|
|
390
|
-
detail: linked ? `symlink \u2192 ${
|
|
419
|
+
detail: linked ? `symlink \u2192 ${join3(sourcePath, mainFileName("command"))}` : "slash command file"
|
|
391
420
|
});
|
|
392
421
|
}
|
|
393
422
|
return changes;
|
|
@@ -407,8 +436,8 @@ var commandHandler = {
|
|
|
407
436
|
};
|
|
408
437
|
|
|
409
438
|
// src/handlers/hook.ts
|
|
410
|
-
import { join as
|
|
411
|
-
import { homedir as
|
|
439
|
+
import { join as join4, basename, dirname } from "path";
|
|
440
|
+
import { homedir as homedir4 } from "os";
|
|
412
441
|
import { lstat as lstat3, mkdir, mkdtemp, readFile, realpath, rm, unlink as unlink3 } from "fs/promises";
|
|
413
442
|
import chalk4 from "chalk";
|
|
414
443
|
import ora3 from "ora";
|
|
@@ -416,10 +445,10 @@ var CLAUDE_ONLY_ERROR = "Hooks are only supported for Claude Code";
|
|
|
416
445
|
var SCRIPT_NAME_LABEL = "hook script name";
|
|
417
446
|
var SCRIPT_MODE = 493;
|
|
418
447
|
function getScopeRoot(scope, cwd) {
|
|
419
|
-
return scope === "user" ?
|
|
448
|
+
return scope === "user" ? homedir4() : cwd;
|
|
420
449
|
}
|
|
421
450
|
function getHooksDir(scope, cwd) {
|
|
422
|
-
return scope === "user" ?
|
|
451
|
+
return scope === "user" ? join4(claudeUserRoot(), "hooks") : join4(getScopeRoot(scope, cwd), ".claude", "hooks");
|
|
423
452
|
}
|
|
424
453
|
function getScriptPath(scope, scriptName) {
|
|
425
454
|
switch (scope) {
|
|
@@ -465,13 +494,13 @@ async function assertRegularFileOrMissing(path) {
|
|
|
465
494
|
async function loadScriptBytes(item, scriptFile, hooksDir) {
|
|
466
495
|
const sourcePath = getItemSourcePath(item);
|
|
467
496
|
if (sourcePath && await exists(sourcePath)) {
|
|
468
|
-
return readFile(
|
|
497
|
+
return readFile(join4(sourcePath, scriptFile));
|
|
469
498
|
}
|
|
470
|
-
const fetchDir = await mkdtemp(
|
|
499
|
+
const fetchDir = await mkdtemp(join4(dirname(hooksDir), ".seedr-hook-"));
|
|
471
500
|
try {
|
|
472
|
-
const contentDir =
|
|
501
|
+
const contentDir = join4(fetchDir, "content");
|
|
473
502
|
await fetchItemToDestination(item, contentDir);
|
|
474
|
-
return await readFile(
|
|
503
|
+
return await readFile(join4(contentDir, scriptFile));
|
|
475
504
|
} finally {
|
|
476
505
|
await rm(fetchDir, { recursive: true, force: true });
|
|
477
506
|
}
|
|
@@ -1219,18 +1248,18 @@ var settingsHandler = {
|
|
|
1219
1248
|
};
|
|
1220
1249
|
|
|
1221
1250
|
// src/handlers/plugin.ts
|
|
1222
|
-
import { join as
|
|
1251
|
+
import { join as join6, relative as relative3 } from "path";
|
|
1223
1252
|
import { mkdir as mkdir3, mkdtemp as mkdtemp2, rm as rm2, stat } from "fs/promises";
|
|
1224
1253
|
import chalk7 from "chalk";
|
|
1225
1254
|
import ora6 from "ora";
|
|
1226
1255
|
|
|
1227
1256
|
// src/handlers/pluginStores.ts
|
|
1228
|
-
import { homedir as
|
|
1229
|
-
import { basename as basename2, dirname as dirname3, isAbsolute, join as
|
|
1257
|
+
import { homedir as homedir5 } from "os";
|
|
1258
|
+
import { basename as basename2, dirname as dirname3, isAbsolute, join as join5 } from "path";
|
|
1230
1259
|
import { mkdir as mkdir2, readFile as readFile3, writeFile } from "fs/promises";
|
|
1231
1260
|
import { execFile } from "child_process";
|
|
1232
1261
|
import { promisify } from "util";
|
|
1233
|
-
var home =
|
|
1262
|
+
var home = homedir5();
|
|
1234
1263
|
var CLAUDE_MANIFEST = ".claude-plugin/plugin.json";
|
|
1235
1264
|
async function readTextOrEmpty2(path) {
|
|
1236
1265
|
try {
|
|
@@ -1240,7 +1269,7 @@ async function readTextOrEmpty2(path) {
|
|
|
1240
1269
|
}
|
|
1241
1270
|
}
|
|
1242
1271
|
async function writeText(path, text) {
|
|
1243
|
-
await mkdir2(
|
|
1272
|
+
await mkdir2(join5(path, ".."), { recursive: true });
|
|
1244
1273
|
await writeFile(path, text, "utf-8");
|
|
1245
1274
|
}
|
|
1246
1275
|
function getPluginId(name, marketplace) {
|
|
@@ -1255,8 +1284,8 @@ function manifestsFor(ownManifest) {
|
|
|
1255
1284
|
return ownManifest ? [ownManifest, CLAUDE_MANIFEST] : [CLAUDE_MANIFEST];
|
|
1256
1285
|
}
|
|
1257
1286
|
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1258
|
-
var CLAUDE_SELF_MARKETPLACE =
|
|
1259
|
-
var COPILOT_SELF_MARKETPLACE =
|
|
1287
|
+
var CLAUDE_SELF_MARKETPLACE = join5(".claude-plugin", "marketplace.json");
|
|
1288
|
+
var COPILOT_SELF_MARKETPLACE = join5(".github", "plugin", "marketplace.json");
|
|
1260
1289
|
async function alignSelfMarketplace(path, marketplace, name, item) {
|
|
1261
1290
|
const existing = await exists(path) ? await readJson(path) : {};
|
|
1262
1291
|
const plugins = Array.isArray(existing.plugins) ? existing.plugins : [];
|
|
@@ -1272,17 +1301,17 @@ async function alignSelfMarketplace(path, marketplace, name, item) {
|
|
|
1272
1301
|
});
|
|
1273
1302
|
}
|
|
1274
1303
|
async function ensureSelfMarketplace(contentPath, marketplace, name, item, alsoAlign = []) {
|
|
1275
|
-
await alignSelfMarketplace(
|
|
1304
|
+
await alignSelfMarketplace(join5(contentPath, CLAUDE_SELF_MARKETPLACE), marketplace, name, item);
|
|
1276
1305
|
for (const relative4 of alsoAlign) {
|
|
1277
|
-
const path =
|
|
1306
|
+
const path = join5(contentPath, relative4);
|
|
1278
1307
|
if (await exists(path)) await alignSelfMarketplace(path, marketplace, name, item);
|
|
1279
1308
|
}
|
|
1280
1309
|
}
|
|
1281
|
-
var CLAUDE_PLUGINS_DIR =
|
|
1282
|
-
var CLAUDE_CACHE_DIR =
|
|
1283
|
-
var CLAUDE_INSTALLED_PATH =
|
|
1284
|
-
var CLAUDE_KNOWN_MARKETPLACES_PATH =
|
|
1285
|
-
var CLAUDE_MARKETPLACES_DIR =
|
|
1310
|
+
var CLAUDE_PLUGINS_DIR = join5(claudeUserRoot(), "plugins");
|
|
1311
|
+
var CLAUDE_CACHE_DIR = join5(CLAUDE_PLUGINS_DIR, "cache");
|
|
1312
|
+
var CLAUDE_INSTALLED_PATH = join5(CLAUDE_PLUGINS_DIR, "installed_plugins.json");
|
|
1313
|
+
var CLAUDE_KNOWN_MARKETPLACES_PATH = join5(CLAUDE_PLUGINS_DIR, "known_marketplaces.json");
|
|
1314
|
+
var CLAUDE_MARKETPLACES_DIR = join5(CLAUDE_PLUGINS_DIR, "marketplaces");
|
|
1286
1315
|
function isScopeEntry(entry, scope, cwd) {
|
|
1287
1316
|
return entry.scope === scope && (scope === "user" || entry.projectPath === cwd);
|
|
1288
1317
|
}
|
|
@@ -1446,8 +1475,21 @@ var claudeStore = {
|
|
|
1446
1475
|
}
|
|
1447
1476
|
};
|
|
1448
1477
|
var COPILOT_DIR = copilotUserRoot();
|
|
1449
|
-
var COPILOT_SETTINGS_PATH =
|
|
1450
|
-
var COPILOT_PLUGINS_DIR =
|
|
1478
|
+
var COPILOT_SETTINGS_PATH = join5(COPILOT_DIR, "settings.json");
|
|
1479
|
+
var COPILOT_PLUGINS_DIR = join5(COPILOT_DIR, "installed-plugins");
|
|
1480
|
+
var COPILOT_HOOKS_DIR = join5(COPILOT_DIR, "hooks");
|
|
1481
|
+
var COPILOT_PLUGIN_HOOKS = join5("hooks", "hooks-copilot.json");
|
|
1482
|
+
function copilotHooksPath(name) {
|
|
1483
|
+
return resolveContained(COPILOT_HOOKS_DIR, name, "hooks.json");
|
|
1484
|
+
}
|
|
1485
|
+
async function writeCopilotHooks(cachePath, name) {
|
|
1486
|
+
const source = join5(cachePath, COPILOT_PLUGIN_HOOKS);
|
|
1487
|
+
if (!await exists(source)) return;
|
|
1488
|
+
const destination = await copilotHooksPath(name);
|
|
1489
|
+
const hooks = (await readFile3(source, "utf8")).replaceAll("${PLUGIN_ROOT}", cachePath);
|
|
1490
|
+
await mkdir2(dirname3(destination), { recursive: true });
|
|
1491
|
+
await writeFile(destination, hooks);
|
|
1492
|
+
}
|
|
1451
1493
|
var copilotStore = {
|
|
1452
1494
|
manifestPaths: manifestsFor(),
|
|
1453
1495
|
userGlobal: true,
|
|
@@ -1515,7 +1557,14 @@ var copilotStore = {
|
|
|
1515
1557
|
path: COPILOT_SETTINGS_PATH,
|
|
1516
1558
|
detail: `enabledPlugins["${context.pluginId}"] = true`,
|
|
1517
1559
|
apply: () => enableInJsonSettings(COPILOT_SETTINGS_PATH, context.pluginId)
|
|
1518
|
-
}
|
|
1560
|
+
},
|
|
1561
|
+
...context.cachePath ? [
|
|
1562
|
+
{
|
|
1563
|
+
path: join5(COPILOT_HOOKS_DIR, context.name, "hooks.json"),
|
|
1564
|
+
detail: `${COPILOT_PLUGIN_HOOKS} with \${PLUGIN_ROOT} resolved \u2014 only when the plugin ships one`,
|
|
1565
|
+
apply: () => writeCopilotHooks(context.cachePath, context.name)
|
|
1566
|
+
}
|
|
1567
|
+
] : []
|
|
1519
1568
|
],
|
|
1520
1569
|
async listInstalled() {
|
|
1521
1570
|
const settings = await readJson(COPILOT_SETTINGS_PATH);
|
|
@@ -1526,6 +1575,7 @@ var copilotStore = {
|
|
|
1526
1575
|
if (!disabled) return false;
|
|
1527
1576
|
const split = splitPluginId(pluginId);
|
|
1528
1577
|
if (split) {
|
|
1578
|
+
await removePathEntry(dirname3(await copilotHooksPath(split.name)));
|
|
1529
1579
|
let tree;
|
|
1530
1580
|
try {
|
|
1531
1581
|
tree = await resolveContained(COPILOT_PLUGINS_DIR, split.marketplace, split.name);
|
|
@@ -1544,8 +1594,8 @@ var copilotStore = {
|
|
|
1544
1594
|
}
|
|
1545
1595
|
};
|
|
1546
1596
|
var CODEX_DIR = codexUserRoot();
|
|
1547
|
-
var CODEX_CONFIG_PATH =
|
|
1548
|
-
var CODEX_CACHE_DIR =
|
|
1597
|
+
var CODEX_CONFIG_PATH = join5(CODEX_DIR, "config.toml");
|
|
1598
|
+
var CODEX_CACHE_DIR = join5(CODEX_DIR, "plugins", "cache");
|
|
1549
1599
|
function toCodexMarketplaceTable(marketplace, url, revision) {
|
|
1550
1600
|
return {
|
|
1551
1601
|
keyPath: ["marketplaces", marketplace],
|
|
@@ -1617,9 +1667,9 @@ var codexStore = {
|
|
|
1617
1667
|
}
|
|
1618
1668
|
};
|
|
1619
1669
|
function openCodeConfigPath(scope, cwd) {
|
|
1620
|
-
return scope === "user" ?
|
|
1670
|
+
return scope === "user" ? join5(openCodeUserConfigDir(), "opencode.json") : join5(cwd, "opencode.json");
|
|
1621
1671
|
}
|
|
1622
|
-
var OPENCODE_PLUGINS_DIR =
|
|
1672
|
+
var OPENCODE_PLUGINS_DIR = join5(openCodeUserConfigDir(), "plugins");
|
|
1623
1673
|
function toOpenCodePluginSpec(item, name, cachePath) {
|
|
1624
1674
|
if (isFirstParty(item.sourceType)) {
|
|
1625
1675
|
if (!cachePath) throw new Error(`OpenCode cannot install "${name}": a first-party plugin needs a directory to load from`);
|
|
@@ -1691,17 +1741,17 @@ var openCodeStore = {
|
|
|
1691
1741
|
return true;
|
|
1692
1742
|
}
|
|
1693
1743
|
};
|
|
1694
|
-
var
|
|
1695
|
-
var
|
|
1696
|
-
var
|
|
1744
|
+
var ANTIGRAVITY_CONFIG_DIR = join5(home, ".gemini", "config");
|
|
1745
|
+
var ANTIGRAVITY_PLUGINS_DIR = join5(ANTIGRAVITY_CONFIG_DIR, "plugins");
|
|
1746
|
+
var ANTIGRAVITY_IMPORT_MANIFEST_PATH = join5(ANTIGRAVITY_CONFIG_DIR, "import_manifest.json");
|
|
1697
1747
|
var antigravityStore = {
|
|
1698
1748
|
manifestPaths: manifestsFor(),
|
|
1699
1749
|
userGlobal: true,
|
|
1700
1750
|
// Filed by name from a tree, so a first-party copy is as good as any other.
|
|
1701
1751
|
firstParty: true,
|
|
1702
|
-
cacheRoot:
|
|
1752
|
+
cacheRoot: ANTIGRAVITY_PLUGINS_DIR,
|
|
1703
1753
|
// Antigravity files plugins by name only — it has no marketplace dimension.
|
|
1704
|
-
cachePath: (_marketplace, name) => resolveContained(
|
|
1754
|
+
cachePath: (_marketplace, name) => resolveContained(ANTIGRAVITY_PLUGINS_DIR, name),
|
|
1705
1755
|
/**
|
|
1706
1756
|
* Antigravity discovers a plugin by a `plugin.json` at the tree ROOT, and
|
|
1707
1757
|
* `.claude-plugin/plugin.json` is not a substitute: the cross-tool matrix
|
|
@@ -1715,7 +1765,7 @@ var antigravityStore = {
|
|
|
1715
1765
|
* (compound-engineering does) is left exactly as it is.
|
|
1716
1766
|
*/
|
|
1717
1767
|
async prepareTree(contentPath, { name, version, item }) {
|
|
1718
|
-
const manifestPath =
|
|
1768
|
+
const manifestPath = join5(contentPath, "plugin.json");
|
|
1719
1769
|
if (await exists(manifestPath)) return;
|
|
1720
1770
|
await writeJson(manifestPath, {
|
|
1721
1771
|
name,
|
|
@@ -1725,10 +1775,10 @@ var antigravityStore = {
|
|
|
1725
1775
|
},
|
|
1726
1776
|
mutations: (context) => [
|
|
1727
1777
|
{
|
|
1728
|
-
path:
|
|
1778
|
+
path: ANTIGRAVITY_IMPORT_MANIFEST_PATH,
|
|
1729
1779
|
detail: `imports[] += "${context.name}"`,
|
|
1730
1780
|
apply: async () => {
|
|
1731
|
-
const manifest = await readJson(
|
|
1781
|
+
const manifest = await readJson(ANTIGRAVITY_IMPORT_MANIFEST_PATH);
|
|
1732
1782
|
const imports = manifest.imports || [];
|
|
1733
1783
|
manifest.imports = [
|
|
1734
1784
|
...imports.filter((entry) => entry.name !== context.name),
|
|
@@ -1739,24 +1789,24 @@ var antigravityStore = {
|
|
|
1739
1789
|
components: ["skills", "hooks"]
|
|
1740
1790
|
}
|
|
1741
1791
|
];
|
|
1742
|
-
await writeJson(
|
|
1792
|
+
await writeJson(ANTIGRAVITY_IMPORT_MANIFEST_PATH, manifest);
|
|
1743
1793
|
}
|
|
1744
1794
|
}
|
|
1745
1795
|
],
|
|
1746
1796
|
async listInstalled() {
|
|
1747
|
-
const manifest = await readJson(
|
|
1797
|
+
const manifest = await readJson(ANTIGRAVITY_IMPORT_MANIFEST_PATH);
|
|
1748
1798
|
return (manifest.imports || []).map((entry) => entry.name);
|
|
1749
1799
|
},
|
|
1750
1800
|
async remove(pluginId) {
|
|
1751
1801
|
const name = splitPluginId(pluginId)?.name ?? pluginId;
|
|
1752
|
-
const manifest = await readJson(
|
|
1802
|
+
const manifest = await readJson(ANTIGRAVITY_IMPORT_MANIFEST_PATH);
|
|
1753
1803
|
const imports = manifest.imports || [];
|
|
1754
1804
|
const remaining = imports.filter((entry) => entry.name !== name);
|
|
1755
1805
|
if (remaining.length === imports.length) return false;
|
|
1756
1806
|
manifest.imports = remaining;
|
|
1757
|
-
await writeJson(
|
|
1807
|
+
await writeJson(ANTIGRAVITY_IMPORT_MANIFEST_PATH, manifest);
|
|
1758
1808
|
try {
|
|
1759
|
-
await removePathEntry(await resolveContained(
|
|
1809
|
+
await removePathEntry(await resolveContained(ANTIGRAVITY_PLUGINS_DIR, name));
|
|
1760
1810
|
} catch {
|
|
1761
1811
|
}
|
|
1762
1812
|
return true;
|
|
@@ -1779,11 +1829,10 @@ var STORES = {
|
|
|
1779
1829
|
copilot: copilotStore,
|
|
1780
1830
|
codex: codexStore,
|
|
1781
1831
|
opencode: openCodeStore,
|
|
1782
|
-
antigravity: antigravityStore
|
|
1783
|
-
gemini: antigravityStore
|
|
1832
|
+
antigravity: antigravityStore
|
|
1784
1833
|
};
|
|
1785
1834
|
function pluginStoreFor(agent) {
|
|
1786
|
-
const store = STORES[
|
|
1835
|
+
const store = STORES[agent];
|
|
1787
1836
|
if (!store || !isTypeSupported("plugin", agent)) {
|
|
1788
1837
|
throw new Error(`Plugins are not supported for ${CODING_AGENTS[agent]?.name ?? agent}`);
|
|
1789
1838
|
}
|
|
@@ -1814,7 +1863,7 @@ function resolvePluginIdentity(item, pluginJson) {
|
|
|
1814
1863
|
}
|
|
1815
1864
|
async function readManifestFromDir(dir, manifestPaths) {
|
|
1816
1865
|
for (const manifest of manifestPaths) {
|
|
1817
|
-
const path =
|
|
1866
|
+
const path = join6(dir, ...manifest.split("/"));
|
|
1818
1867
|
if (await exists(path)) return readJson(path);
|
|
1819
1868
|
}
|
|
1820
1869
|
return {};
|
|
@@ -1833,7 +1882,7 @@ async function readManifestForPlan(item, manifestPaths) {
|
|
|
1833
1882
|
async function createStagingDir(cacheRoot, slug) {
|
|
1834
1883
|
const tmpRoot = await resolveContained(cacheRoot, ".tmp");
|
|
1835
1884
|
await mkdir3(tmpRoot, { recursive: true });
|
|
1836
|
-
const staging = await mkdtemp2(
|
|
1885
|
+
const staging = await mkdtemp2(join6(tmpRoot, `${slug}-`));
|
|
1837
1886
|
return resolveContained(cacheRoot, relative3(cacheRoot, staging));
|
|
1838
1887
|
}
|
|
1839
1888
|
async function stageContent(item, contentPath) {
|
|
@@ -1901,7 +1950,7 @@ async function installPluginForAgent(item, agent, scope, _method, force, cwd) {
|
|
|
1901
1950
|
const cacheRoot = store.cacheRoot ?? (isFirstParty(item.sourceType) ? store.firstPartyCacheRoot ?? null : null);
|
|
1902
1951
|
const staging = cacheRoot ? await createStagingDir(cacheRoot, item.slug) : null;
|
|
1903
1952
|
try {
|
|
1904
|
-
const contentPath = staging ?
|
|
1953
|
+
const contentPath = staging ? join6(staging, "content") : null;
|
|
1905
1954
|
const fetched = contentPath ? await stageContent(item, contentPath) : null;
|
|
1906
1955
|
const pluginJson = contentPath ? await readManifestFromDir(contentPath, store.manifestPaths) : await readManifestForPlan(item, store.manifestPaths);
|
|
1907
1956
|
const { name, version } = resolvePluginIdentity(item, pluginJson);
|
|
@@ -1929,7 +1978,7 @@ async function installPluginForAgent(item, agent, scope, _method, force, cwd) {
|
|
|
1929
1978
|
...store.mutations(context)
|
|
1930
1979
|
]);
|
|
1931
1980
|
spinner.succeed(brand(`Installed ${item.name} for ${CODING_AGENTS[agent].name}`));
|
|
1932
|
-
return { agent, success: true, path: cachePath ?? "" };
|
|
1981
|
+
return { agent, success: true, path: cachePath ?? "", version };
|
|
1933
1982
|
} finally {
|
|
1934
1983
|
if (staging) await rm2(staging, { recursive: true, force: true });
|
|
1935
1984
|
}
|
|
@@ -2056,46 +2105,45 @@ import chalk8 from "chalk";
|
|
|
2056
2105
|
import ora7 from "ora";
|
|
2057
2106
|
|
|
2058
2107
|
// src/handlers/ruleTargets.ts
|
|
2059
|
-
import { homedir as
|
|
2060
|
-
import { join as
|
|
2061
|
-
var home2 =
|
|
2108
|
+
import { homedir as homedir6 } from "os";
|
|
2109
|
+
import { join as join7 } from "path";
|
|
2110
|
+
var home2 = homedir6();
|
|
2062
2111
|
var markdownFile = (slug) => `${slug}.md`;
|
|
2063
2112
|
var claudeTarget = {
|
|
2064
2113
|
kind: "file",
|
|
2065
|
-
dir: (scope, cwd) =>
|
|
2114
|
+
dir: (scope, cwd) => join7(scope === "user" ? claudeUserRoot() : join7(cwd, ".claude"), "rules"),
|
|
2066
2115
|
fileName: markdownFile,
|
|
2067
2116
|
keepsFrontmatter: true
|
|
2068
2117
|
};
|
|
2069
2118
|
var antigravityTarget = {
|
|
2070
2119
|
kind: "file",
|
|
2071
|
-
dir: (scope, cwd) =>
|
|
2120
|
+
dir: (scope, cwd) => join7(scope === "user" ? join7(home2, ".gemini", "config") : join7(cwd, ".agents"), "rules"),
|
|
2072
2121
|
fileName: markdownFile,
|
|
2073
2122
|
keepsFrontmatter: true
|
|
2074
2123
|
};
|
|
2075
2124
|
var copilotTarget = {
|
|
2076
2125
|
kind: "file",
|
|
2077
|
-
dir: (scope, cwd) =>
|
|
2126
|
+
dir: (scope, cwd) => join7(scope === "user" ? copilotUserRoot() : join7(cwd, ".github"), "instructions"),
|
|
2078
2127
|
fileName: (slug) => `${slug}.instructions.md`,
|
|
2079
2128
|
keepsFrontmatter: true
|
|
2080
2129
|
};
|
|
2081
2130
|
var codexTarget = {
|
|
2082
2131
|
kind: "section",
|
|
2083
|
-
file: (scope, cwd) => scope === "user" ?
|
|
2132
|
+
file: (scope, cwd) => scope === "user" ? join7(codexUserRoot(), "AGENTS.md") : join7(cwd, "AGENTS.md")
|
|
2084
2133
|
};
|
|
2085
2134
|
var openCodeTarget = {
|
|
2086
2135
|
kind: "section",
|
|
2087
|
-
file: (scope, cwd) => scope === "user" ?
|
|
2136
|
+
file: (scope, cwd) => scope === "user" ? join7(openCodeUserConfigDir(), "AGENTS.md") : join7(cwd, "AGENTS.md")
|
|
2088
2137
|
};
|
|
2089
2138
|
var TARGETS = {
|
|
2090
2139
|
claude: claudeTarget,
|
|
2091
2140
|
antigravity: antigravityTarget,
|
|
2092
|
-
gemini: antigravityTarget,
|
|
2093
2141
|
copilot: copilotTarget,
|
|
2094
2142
|
codex: codexTarget,
|
|
2095
2143
|
opencode: openCodeTarget
|
|
2096
2144
|
};
|
|
2097
2145
|
function ruleTargetFor(agent) {
|
|
2098
|
-
const target = TARGETS[
|
|
2146
|
+
const target = TARGETS[agent];
|
|
2099
2147
|
if (!target || !isTypeSupported("rule", agent)) {
|
|
2100
2148
|
throw new Error(`Rules are not supported for ${CODING_AGENTS[agent]?.name ?? agent}`);
|
|
2101
2149
|
}
|
|
@@ -2291,12 +2339,11 @@ function resolveRequestedAgents(agentsArg, item) {
|
|
|
2291
2339
|
if (agentsArg === void 0 || agentsArg.trim() === "") {
|
|
2292
2340
|
return { ok: true, agents: [], explicit: false };
|
|
2293
2341
|
}
|
|
2294
|
-
const deprecationWarning = agentsArg.split(",").map((raw) => raw.trim().toLowerCase()).some((id) => isLegacyAgent(id)) ? "'gemini' is now 'antigravity' (Google Antigravity, installs to .agents/)" : void 0;
|
|
2295
2342
|
if (agentsArg.trim() === "all") {
|
|
2296
2343
|
if (compatible.length === 0) {
|
|
2297
2344
|
return { ok: false, error: `No agent supports ${item.type} "${item.slug}"` };
|
|
2298
2345
|
}
|
|
2299
|
-
return { ok: true, agents: compatible, explicit: true
|
|
2346
|
+
return { ok: true, agents: compatible, explicit: true };
|
|
2300
2347
|
}
|
|
2301
2348
|
const { agents, unknown } = parseAgentsArgStrict(agentsArg);
|
|
2302
2349
|
if (unknown.length > 0) {
|
|
@@ -2316,7 +2363,7 @@ function resolveRequestedAgents(agentsArg, item) {
|
|
|
2316
2363
|
error: `Cannot install ${item.type} "${item.slug}" for ${incompatible.join(", ")}. Compatible agents: ${compatibleList}. ${reasons.join("; ")}`
|
|
2317
2364
|
};
|
|
2318
2365
|
}
|
|
2319
|
-
return { ok: true, agents, explicit: true
|
|
2366
|
+
return { ok: true, agents, explicit: true };
|
|
2320
2367
|
}
|
|
2321
2368
|
function decideForce(options) {
|
|
2322
2369
|
return Boolean(options.force) || !options.yes;
|
|
@@ -2354,6 +2401,24 @@ function formatPlan(changes) {
|
|
|
2354
2401
|
}
|
|
2355
2402
|
return lines;
|
|
2356
2403
|
}
|
|
2404
|
+
async function noteInstall(item, results, scope) {
|
|
2405
|
+
const succeeded = results.filter((r) => r.success);
|
|
2406
|
+
const installed = succeeded.map((r) => r.agent);
|
|
2407
|
+
if (installed.length === 0) return;
|
|
2408
|
+
try {
|
|
2409
|
+
await recordInstall({
|
|
2410
|
+
type: item.type,
|
|
2411
|
+
slug: item.slug,
|
|
2412
|
+
version: succeeded.find((r) => r.version)?.version ?? item.version,
|
|
2413
|
+
contentDigest: item.contentDigest,
|
|
2414
|
+
agents: installed,
|
|
2415
|
+
scope,
|
|
2416
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2417
|
+
});
|
|
2418
|
+
} catch (error2) {
|
|
2419
|
+
warn(`Installed, but the install record could not be written: ${error2.message}`);
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2357
2422
|
function summarizeResults(results) {
|
|
2358
2423
|
const successful = results.filter((r) => r.success);
|
|
2359
2424
|
const failed = results.filter((r) => !r.success);
|
|
@@ -2421,7 +2486,6 @@ async function chooseAgents(options, item) {
|
|
|
2421
2486
|
error(resolution.error);
|
|
2422
2487
|
return null;
|
|
2423
2488
|
}
|
|
2424
|
-
if (resolution.deprecationWarning) warn(resolution.deprecationWarning);
|
|
2425
2489
|
if (resolution.agents.length > 0) return resolution.agents;
|
|
2426
2490
|
const compatible = compatibleAgentsFor(item);
|
|
2427
2491
|
if (compatible.length === 0) {
|
|
@@ -2526,13 +2590,14 @@ async function runAdd(name, options, cwd = process.cwd()) {
|
|
|
2526
2590
|
console.log();
|
|
2527
2591
|
const results = await handler.install(item, agents, scope, method, decideForce(options), cwd);
|
|
2528
2592
|
void trackInstalls(item.slug, item.type, results, scope);
|
|
2593
|
+
await noteInstall(item, results, scope);
|
|
2529
2594
|
const exitCode = printInstallSummary(results);
|
|
2530
2595
|
if (exitCode === 0) outro("Installation complete");
|
|
2531
2596
|
return exitCode;
|
|
2532
2597
|
}
|
|
2533
2598
|
var addCommand = new Command("add").description("Install a skill, agent, hook, or other configuration").argument("[name]", "Name of the item to install").option("-t, --type <type>", `Content type: ${TYPE_LIST}`).option(
|
|
2534
2599
|
"-a, --agents <agents>",
|
|
2535
|
-
"Comma-separated coding agents or 'all' (claude,copilot,antigravity,codex,opencode
|
|
2600
|
+
"Comma-separated coding agents or 'all' (claude,copilot,antigravity,codex,opencode). Every named agent must support the item; 'all' means all compatible agents. MCP servers: claude, codex, opencode (copilot's and antigravity's formats are unverified)"
|
|
2536
2601
|
).option("-s, --scope <scope>", "Installation scope: project, user, or local").option("-m, --method <method>", "Installation method: symlink or copy").option("-y, --yes", "Skip confirmation prompts").option("-f, --force", "Overwrite existing files").option("-n, --dry-run", "Show exactly which files would be written, without writing or reporting anything").addHelpText("after", `
|
|
2537
2602
|
Telemetry: ${TELEMETRY_HELP_TEXT}.`).action(async (name, options) => {
|
|
2538
2603
|
try {
|
|
@@ -2645,11 +2710,37 @@ ${itemType.toUpperCase()}S`));
|
|
|
2645
2710
|
);
|
|
2646
2711
|
return 0;
|
|
2647
2712
|
}
|
|
2713
|
+
async function installedVersionAnnotator() {
|
|
2714
|
+
let ledger;
|
|
2715
|
+
try {
|
|
2716
|
+
ledger = await readLedger();
|
|
2717
|
+
} catch {
|
|
2718
|
+
return () => "";
|
|
2719
|
+
}
|
|
2720
|
+
let current;
|
|
2721
|
+
try {
|
|
2722
|
+
const items = await listItems();
|
|
2723
|
+
current = new Map(
|
|
2724
|
+
items.filter((item) => item.contentDigest).map((item) => [ledgerKey(item.type, item.slug), item.contentDigest])
|
|
2725
|
+
);
|
|
2726
|
+
} catch {
|
|
2727
|
+
current = /* @__PURE__ */ new Map();
|
|
2728
|
+
}
|
|
2729
|
+
return (type, slug) => {
|
|
2730
|
+
const key = ledgerKey(type, slug);
|
|
2731
|
+
const entry = ledger.items[key];
|
|
2732
|
+
if (!entry?.version) return "";
|
|
2733
|
+
const available = current.get(key);
|
|
2734
|
+
const stale = entry.contentDigest && available && available !== entry.contentDigest;
|
|
2735
|
+
return chalk10.gray(` ${entry.version}`) + (stale ? chalk10.yellow(" \u2192 update available") : "");
|
|
2736
|
+
};
|
|
2737
|
+
}
|
|
2648
2738
|
async function listInstalled(params) {
|
|
2649
2739
|
console.log(brand(`
|
|
2650
2740
|
Installed items (${params.scope} scope):
|
|
2651
2741
|
`));
|
|
2652
2742
|
const groups = await collectInstalledItems(params);
|
|
2743
|
+
const annotate = await installedVersionAnnotator();
|
|
2653
2744
|
let total = 0;
|
|
2654
2745
|
let currentType = null;
|
|
2655
2746
|
for (const group of groups) {
|
|
@@ -2660,7 +2751,7 @@ Installed items (${params.scope} scope):
|
|
|
2660
2751
|
}
|
|
2661
2752
|
console.log(chalk10.blue(` ${CODING_AGENTS[group.agent].name}`));
|
|
2662
2753
|
for (const slug of group.slugs) {
|
|
2663
|
-
console.log(` ${chalk10.white(slug)}`);
|
|
2754
|
+
console.log(` ${chalk10.white(slug)}${annotate(group.type, slug)}`);
|
|
2664
2755
|
total++;
|
|
2665
2756
|
}
|
|
2666
2757
|
console.log("");
|
|
@@ -2707,6 +2798,7 @@ async function removeFromAgents(slug, type, agents, scope, cwd) {
|
|
|
2707
2798
|
const handler = getHandler(type);
|
|
2708
2799
|
if (!handler) return 0;
|
|
2709
2800
|
let successCount = 0;
|
|
2801
|
+
const removedFrom = [];
|
|
2710
2802
|
for (const agent of agents) {
|
|
2711
2803
|
if (!isTypeSupported(type, agent)) {
|
|
2712
2804
|
ora8().start().info(
|
|
@@ -2718,11 +2810,18 @@ async function removeFromAgents(slug, type, agents, scope, cwd) {
|
|
|
2718
2810
|
const removed = await handler.uninstall(slug, agent, scope, cwd);
|
|
2719
2811
|
if (removed) {
|
|
2720
2812
|
spinner.succeed(brand(`Removed from ${CODING_AGENTS[agent].name}`));
|
|
2813
|
+
removedFrom.push(agent);
|
|
2721
2814
|
successCount++;
|
|
2722
2815
|
} else {
|
|
2723
2816
|
spinner.info(chalk11.gray(`Not found in ${CODING_AGENTS[agent].name}`));
|
|
2724
2817
|
}
|
|
2725
2818
|
}
|
|
2819
|
+
if (removedFrom.length > 0) {
|
|
2820
|
+
try {
|
|
2821
|
+
await recordRemoval(type, slug, removedFrom);
|
|
2822
|
+
} catch {
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2726
2825
|
return successCount;
|
|
2727
2826
|
}
|
|
2728
2827
|
function validateRemoveRequest(name, options) {
|
|
@@ -2815,7 +2914,7 @@ var removeCommand = new Command3("remove").alias("rm").description("Remove an in
|
|
|
2815
2914
|
import { Command as Command4 } from "commander";
|
|
2816
2915
|
import chalk12 from "chalk";
|
|
2817
2916
|
import ora9 from "ora";
|
|
2818
|
-
import { join as
|
|
2917
|
+
import { join as join8 } from "path";
|
|
2819
2918
|
function readmeFor(agent) {
|
|
2820
2919
|
return `# ${CODING_AGENTS[agent].name} Configuration
|
|
2821
2920
|
|
|
@@ -2833,7 +2932,7 @@ async function initializeAgent(agent, cwd) {
|
|
|
2833
2932
|
const path = getAgentPath(agent, "project", cwd);
|
|
2834
2933
|
if (await exists(path)) return false;
|
|
2835
2934
|
await ensureDir(path);
|
|
2836
|
-
await writeTextFile(
|
|
2935
|
+
await writeTextFile(join8(path, "README.md"), readmeFor(agent));
|
|
2837
2936
|
return true;
|
|
2838
2937
|
}
|
|
2839
2938
|
async function runInit(options, cwd = process.cwd()) {
|
|
@@ -2894,7 +2993,7 @@ var initCommand = new Command4("init").description("Initialize coding agent conf
|
|
|
2894
2993
|
// package.json
|
|
2895
2994
|
var package_default = {
|
|
2896
2995
|
name: "@danieldeusing/seedr",
|
|
2897
|
-
version: "0.1.
|
|
2996
|
+
version: "0.1.131",
|
|
2898
2997
|
description: "Seed your projects with AI configurations",
|
|
2899
2998
|
type: "module",
|
|
2900
2999
|
bin: {
|
|
@@ -2941,7 +3040,7 @@ var package_default = {
|
|
|
2941
3040
|
"ai",
|
|
2942
3041
|
"claude",
|
|
2943
3042
|
"copilot",
|
|
2944
|
-
"
|
|
3043
|
+
"antigravity",
|
|
2945
3044
|
"codex",
|
|
2946
3045
|
"opencode",
|
|
2947
3046
|
"configuration",
|
package/dist/index.d.ts
CHANGED
|
@@ -43,10 +43,7 @@ interface InstalledItem {
|
|
|
43
43
|
installedAt: string;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
/**
|
|
47
|
-
* Where each agent keeps what. The deprecated `gemini` id shares Antigravity's
|
|
48
|
-
* layout, so an old flag or an unmigrated item still installs to the right place.
|
|
49
|
-
*/
|
|
46
|
+
/** Where each agent keeps what. */
|
|
50
47
|
declare const CODING_AGENTS: Record<CodingAgent, CodingAgentConfig>;
|
|
51
48
|
/** The agents `--agents all` expands to: canonical ids only. */
|
|
52
49
|
declare const ALL_AGENTS: CodingAgent[];
|
|
@@ -72,6 +69,13 @@ interface InstallResult {
|
|
|
72
69
|
success: boolean;
|
|
73
70
|
path: string;
|
|
74
71
|
error?: string;
|
|
72
|
+
/**
|
|
73
|
+
* The version that landed, when it differs from the registry item's own.
|
|
74
|
+
* A plugin carries its version in its manifest and the registry item carries
|
|
75
|
+
* a separate one for the catalogue entry — recording the item's would say
|
|
76
|
+
* "1.0.20" for a plugin every agent knows as 0.16.2.
|
|
77
|
+
*/
|
|
78
|
+
version?: string;
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
declare function installSkill(item: RegistryItem, agents: CodingAgent[], scope: InstallScope, method: InstallMethod, force: boolean, cwd?: string): Promise<InstallResult[]>;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danieldeusing/seedr",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.131",
|
|
4
4
|
"description": "Seed your projects with AI configurations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"ai",
|
|
48
48
|
"claude",
|
|
49
49
|
"copilot",
|
|
50
|
-
"
|
|
50
|
+
"antigravity",
|
|
51
51
|
"codex",
|
|
52
52
|
"opencode",
|
|
53
53
|
"configuration",
|