@danieldeusing/seedr 0.1.91 → 0.1.92

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.
@@ -2,12 +2,22 @@
2
2
 
3
3
  // src/config/registry.ts
4
4
  import { readFile as readFile3, readdir, writeFile as writeFile2, mkdir as mkdir2, mkdtemp, rm as rm2 } from "fs/promises";
5
- import { existsSync } from "fs";
5
+ import { existsSync as existsSync7 } from "fs";
6
6
  import { tmpdir } from "os";
7
- import { join as join3, dirname as dirname2 } from "path";
7
+ import { join as join8, dirname as dirname4 } from "path";
8
8
  import { fileURLToPath } from "url";
9
9
 
10
10
  // ../registry-ops/src/paths.ts
11
+ var DEFAULT_REGISTRY_DIR = "registry";
12
+ function registryDirName(config) {
13
+ if (typeof config !== "object" || config === null) return DEFAULT_REGISTRY_DIR;
14
+ const value = config.registryDir;
15
+ if (value === void 0) return DEFAULT_REGISTRY_DIR;
16
+ if (typeof value !== "string" || !/^registry[a-z0-9._-]*$/i.test(value)) {
17
+ throw new Error(`seedr.config.json: registryDir must be a single directory name starting with "registry", not ${JSON.stringify(value)}`);
18
+ }
19
+ return value;
20
+ }
11
21
  var ALL_TYPES = ["skill", "plugin", "hook", "agent", "mcp", "settings", "command"];
12
22
  var KNOWN_TYPES = new Set(ALL_TYPES);
13
23
  function typeDirName(type) {
@@ -36,23 +46,75 @@ function canonicalAgents(values) {
36
46
 
37
47
  // ../registry-ops/src/sourceTypes.ts
38
48
  var CANONICAL_SOURCE_TYPES = ["official", "seedr", "community"];
39
- var SOURCE_TYPE_ALIASES = { toolr: "seedr" };
40
- var KNOWN_SOURCE_TYPES = [...CANONICAL_SOURCE_TYPES, ...Object.keys(SOURCE_TYPE_ALIASES)];
41
49
  function isCanonicalSourceType(value) {
42
50
  return typeof value === "string" && CANONICAL_SOURCE_TYPES.includes(value);
43
51
  }
44
- function isLegacySourceType(value) {
45
- return typeof value === "string" && Object.hasOwn(SOURCE_TYPE_ALIASES, value);
46
- }
47
52
  function canonicalSourceType(value) {
48
- if (isCanonicalSourceType(value)) return value;
49
- if (isLegacySourceType(value)) return SOURCE_TYPE_ALIASES[value];
50
- return null;
53
+ return isCanonicalSourceType(value) ? value : null;
51
54
  }
52
55
  function isFirstParty(sourceType) {
53
56
  return canonicalSourceType(sourceType) === "seedr";
54
57
  }
55
58
 
59
+ // ../registry-ops/src/fsPaths.ts
60
+ import { existsSync, readFileSync } from "fs";
61
+ import { join } from "path";
62
+ var REPO_CONFIG_FILE = "seedr.config.json";
63
+ function resolveRegistryDir(repoRoot) {
64
+ const config = join(repoRoot, REPO_CONFIG_FILE);
65
+ if (!existsSync(config)) return join(repoRoot, DEFAULT_REGISTRY_DIR);
66
+ let parsed;
67
+ try {
68
+ parsed = JSON.parse(readFileSync(config, "utf8"));
69
+ } catch (error2) {
70
+ throw new Error(`${REPO_CONFIG_FILE} is not readable JSON: ${error2.message}`, { cause: error2 });
71
+ }
72
+ return join(repoRoot, registryDirName(parsed));
73
+ }
74
+
75
+ // ../registry-ops/src/hash.ts
76
+ import { createHash } from "crypto";
77
+ import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync2 } from "fs";
78
+ import { join as join2, relative } from "path";
79
+
80
+ // ../registry-ops/src/read.ts
81
+ import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "fs";
82
+ import { join as join3 } from "path";
83
+
84
+ // ../registry-ops/src/compile.ts
85
+ import { mkdirSync, writeFileSync } from "fs";
86
+
87
+ // ../registry-ops/src/identity.ts
88
+ import { execFile } from "child_process";
89
+ import { promisify } from "util";
90
+ var execFileAsync = promisify(execFile);
91
+
92
+ // ../registry-ops/src/ops/addLocal.ts
93
+ import { spawnSync } from "child_process";
94
+ import { copyFileSync, existsSync as existsSync4, mkdirSync as mkdirSync2, realpathSync, rmdirSync, rmSync, readdirSync as readdirSync3, statSync, writeFileSync as writeFileSync2 } from "fs";
95
+ import { basename, join as join4 } from "path";
96
+
97
+ // ../registry-ops/src/ops/addRemote.ts
98
+ import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
99
+
100
+ // ../registry-ops/src/ops/remove.ts
101
+ import { rmSync as rmSync2 } from "fs";
102
+
103
+ // ../registry-ops/src/ops/setLabels.ts
104
+ import { writeFileSync as writeFileSync4 } from "fs";
105
+
106
+ // ../registry-ops/src/ops/update.ts
107
+ import { existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
108
+ import { dirname, resolve, sep } from "path";
109
+
110
+ // ../registry-ops/src/tx.ts
111
+ import { existsSync as existsSync6, mkdirSync as mkdirSync5, readFileSync as readFileSync4, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "fs";
112
+ import { dirname as dirname2, join as join5, relative as relative2, resolve as resolve2 } from "path";
113
+ var DEFAULT_LOCK_STALE_MS = 10 * 60 * 1e3;
114
+
115
+ // ../registry-ops/src/migrate.ts
116
+ import { writeFileSync as writeFileSync7 } from "fs";
117
+
56
118
  // src/utils/slug.ts
57
119
  var SLUG_PATTERN2 = /^[a-z0-9][a-z0-9-]*$/;
58
120
  var MAX_SLUG_LENGTH2 = 100;
@@ -68,11 +130,11 @@ function assertValidSlug(value, what = "item slug") {
68
130
  }
69
131
 
70
132
  // src/utils/digest.ts
71
- import { createHash } from "crypto";
133
+ import { createHash as createHash2 } from "crypto";
72
134
  import { readFile } from "fs/promises";
73
- import { join } from "path";
135
+ import { join as join6 } from "path";
74
136
  function sha256Hex(bytes) {
75
- return createHash("sha256").update(bytes).digest("hex");
137
+ return createHash2("sha256").update(bytes).digest("hex");
76
138
  }
77
139
  function digestFromFileHashes(entries) {
78
140
  const sorted = [...entries].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
@@ -88,7 +150,7 @@ async function computeContentDigest(root, relativePaths) {
88
150
  const entries = await Promise.all(
89
151
  relativePaths.map(async (relativePath) => ({
90
152
  path: relativePath,
91
- sha256: sha256Hex(await readFile(join(root, ...relativePath.split("/"))))
153
+ sha256: sha256Hex(await readFile(join6(root, ...relativePath.split("/"))))
92
154
  }))
93
155
  );
94
156
  return digestFromFileHashes(entries);
@@ -132,7 +194,7 @@ import {
132
194
  } from "fs/promises";
133
195
  import { randomBytes } from "crypto";
134
196
  import { homedir } from "os";
135
- import { basename, dirname, join as join2, relative, resolve, isAbsolute, sep } from "path";
197
+ import { basename as basename2, dirname as dirname3, join as join7, relative as relative3, resolve as resolve3, isAbsolute, sep as sep2 } from "path";
136
198
  async function exists(path) {
137
199
  try {
138
200
  await access(path);
@@ -165,11 +227,11 @@ function assertSafePathSegment(value, what) {
165
227
  }
166
228
  }
167
229
  function isStrictDescendant(root, candidate) {
168
- const rel = relative(root, candidate);
169
- return rel !== "" && !isAbsolute(rel) && rel !== ".." && !rel.startsWith(`..${sep}`);
230
+ const rel = relative3(root, candidate);
231
+ return rel !== "" && !isAbsolute(rel) && rel !== ".." && !rel.startsWith(`..${sep2}`);
170
232
  }
171
233
  function isSameOrDescendant(root, candidate) {
172
- return relative(root, candidate) === "" || isStrictDescendant(root, candidate);
234
+ return relative3(root, candidate) === "" || isStrictDescendant(root, candidate);
173
235
  }
174
236
  async function realpathOrNull(path) {
175
237
  try {
@@ -179,8 +241,8 @@ async function realpathOrNull(path) {
179
241
  }
180
242
  }
181
243
  async function resolveContained(root, ...segments) {
182
- const absoluteRoot = resolve(root);
183
- const resolved = resolve(absoluteRoot, ...segments);
244
+ const absoluteRoot = resolve3(root);
245
+ const resolved = resolve3(absoluteRoot, ...segments);
184
246
  if (!isStrictDescendant(absoluteRoot, resolved)) {
185
247
  throw new Error(`Refusing path outside ${absoluteRoot}: ${resolved}`);
186
248
  }
@@ -188,7 +250,7 @@ async function resolveContained(root, ...segments) {
188
250
  if (realRoot === null) {
189
251
  return resolved;
190
252
  }
191
- let ancestor = dirname(resolved);
253
+ let ancestor = dirname3(resolved);
192
254
  for (; ; ) {
193
255
  const realAncestor = await realpathOrNull(ancestor);
194
256
  if (realAncestor !== null) {
@@ -199,16 +261,16 @@ async function resolveContained(root, ...segments) {
199
261
  }
200
262
  return resolved;
201
263
  }
202
- const parent = dirname(ancestor);
203
- if (parent === ancestor || relative(absoluteRoot, ancestor) === "") {
264
+ const parent = dirname3(ancestor);
265
+ if (parent === ancestor || relative3(absoluteRoot, ancestor) === "") {
204
266
  return resolved;
205
267
  }
206
268
  ancestor = parent;
207
269
  }
208
270
  }
209
271
  async function assertDirectoryWithin(dir, scopeRoot, what) {
210
- const realRoot = await realpathOrNull(resolve(scopeRoot));
211
- const realDir = await realpathOrNull(resolve(dir));
272
+ const realRoot = await realpathOrNull(resolve3(scopeRoot));
273
+ const realDir = await realpathOrNull(resolve3(dir));
212
274
  if (realRoot === null || realDir === null) {
213
275
  throw new Error(`${what} ${dir} could not be resolved`);
214
276
  }
@@ -232,7 +294,7 @@ async function removePathEntry(path) {
232
294
  return true;
233
295
  }
234
296
  async function moveDirectory(source, destination) {
235
- await mkdir(dirname(destination), { recursive: true });
297
+ await mkdir(dirname3(destination), { recursive: true });
236
298
  try {
237
299
  await rename(source, destination);
238
300
  } catch (error2) {
@@ -242,7 +304,7 @@ async function moveDirectory(source, destination) {
242
304
  }
243
305
  }
244
306
  async function writeFileAtomic(path, data, options = {}) {
245
- const tempPath = join2(dirname(path), `${basename(path)}.${randomBytes(6).toString("hex")}.tmp`);
307
+ const tempPath = join7(dirname3(path), `${basename2(path)}.${randomBytes(6).toString("hex")}.tmp`);
246
308
  try {
247
309
  await writeFile(tempPath, data, options.mode === void 0 ? {} : { mode: options.mode });
248
310
  await rename(tempPath, path);
@@ -268,31 +330,31 @@ async function restoreFile(path, snapshot) {
268
330
  await writeFileAtomic(path, snapshot.content, { mode: snapshot.mode });
269
331
  }
270
332
  async function installFile(source, destination, method) {
271
- await ensureDir(dirname(destination));
333
+ await ensureDir(dirname3(destination));
272
334
  await removePathEntry(destination);
273
335
  if (method === "symlink") {
274
- const relPath = relative(dirname(destination), source);
336
+ const relPath = relative3(dirname3(destination), source);
275
337
  await symlink(relPath, destination);
276
338
  } else {
277
339
  await copyFile(source, destination);
278
340
  }
279
341
  }
280
342
  async function writeTextFile(path, content) {
281
- await ensureDir(dirname(path));
343
+ await ensureDir(dirname3(path));
282
344
  await writeFile(path, content, "utf-8");
283
345
  }
284
346
  function getAgentsPath(contentType, slug, scope, cwd) {
285
347
  const base = scope === "user" ? homedir() : cwd;
286
- return join2(base, ".agents", contentType + "s", slug);
348
+ return join7(base, ".agents", contentType + "s", slug);
287
349
  }
288
350
  async function copyDirectory(source, destination) {
289
351
  await cp(source, destination, { recursive: true });
290
352
  }
291
353
  async function installDirectory(source, destination, method) {
292
- await ensureDir(dirname(destination));
354
+ await ensureDir(dirname3(destination));
293
355
  await removePathEntry(destination);
294
356
  if (method === "symlink") {
295
- const relPath = relative(dirname(destination), source);
357
+ const relPath = relative3(dirname3(destination), source);
296
358
  await symlink(relPath, destination);
297
359
  } else {
298
360
  await copyDirectory(source, destination);
@@ -403,13 +465,13 @@ function resolveItemSource(item) {
403
465
  }
404
466
 
405
467
  // src/config/registry.ts
406
- var __dirname2 = dirname2(fileURLToPath(import.meta.url));
468
+ var __dirname2 = dirname4(fileURLToPath(import.meta.url));
407
469
  var FETCH_TIMEOUT_MS = 15e3;
408
470
  function findPackageRoot(startDir) {
409
471
  let dir = startDir;
410
472
  for (; ; ) {
411
- if (existsSync(join3(dir, "package.json"))) return dir;
412
- const parent = dirname2(dir);
473
+ if (existsSync7(join8(dir, "package.json"))) return dir;
474
+ const parent = dirname4(dir);
413
475
  if (parent === dir) return null;
414
476
  dir = parent;
415
477
  }
@@ -417,7 +479,7 @@ function findPackageRoot(startDir) {
417
479
  function resolveLocalRegistryPath() {
418
480
  const packageRoot = findPackageRoot(__dirname2);
419
481
  if (!packageRoot) return null;
420
- return join3(packageRoot, "..", "..", "registry");
482
+ return resolveRegistryDir(join8(packageRoot, "..", ".."));
421
483
  }
422
484
  var REGISTRY_PATH = process.env.SEEDR_REGISTRY_DIR || resolveLocalRegistryPath();
423
485
  var DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/danieldeusing/seedr/main/registry";
@@ -439,7 +501,7 @@ function isValidManifestIndex(value) {
439
501
  async function loadFile(filename) {
440
502
  if (REGISTRY_PATH) {
441
503
  try {
442
- return await readFile3(join3(REGISTRY_PATH, filename), "utf-8");
504
+ return await readFile3(join8(REGISTRY_PATH, filename), "utf-8");
443
505
  } catch {
444
506
  }
445
507
  }
@@ -472,7 +534,7 @@ async function loadIndex() {
472
534
  if (cache.index) return cache.index;
473
535
  if (REGISTRY_PATH) {
474
536
  try {
475
- const localContent = await readFile3(join3(REGISTRY_PATH, "manifest.json"), "utf-8");
537
+ const localContent = await readFile3(join8(REGISTRY_PATH, "manifest.json"), "utf-8");
476
538
  const parsed = JSON.parse(localContent);
477
539
  if (isValidManifestIndex(parsed)) {
478
540
  cache.index = parsed;
@@ -517,7 +579,7 @@ async function getItemsBySlug(slug) {
517
579
  const manifest = await loadManifest();
518
580
  return manifest.items.filter((item) => item.slug === slug);
519
581
  }
520
- async function listItems(type) {
582
+ async function listItems2(type) {
521
583
  if (type) {
522
584
  return loadTypeItems(type);
523
585
  }
@@ -533,18 +595,18 @@ async function searchItems(query) {
533
595
  }
534
596
  async function getItemFull(item) {
535
597
  assertValidSlug(item.slug);
536
- const typeDir = typeDirName(item.type);
537
- const itemJsonPath = `${typeDir}/${item.slug}/item.json`;
538
- const content = await loadFile(itemJsonPath);
598
+ const typeDir2 = typeDirName(item.type);
599
+ const itemJsonPath2 = `${typeDir2}/${item.slug}/item.json`;
600
+ const content = await loadFile(itemJsonPath2);
539
601
  return JSON.parse(content);
540
602
  }
541
603
  function getItemBaseUrl(item) {
542
604
  if (isFirstParty(item.sourceType)) {
543
605
  assertValidSlug(item.slug);
544
- const typeDir = typeDirName(item.type);
606
+ const typeDir2 = typeDirName(item.type);
545
607
  return {
546
- local: REGISTRY_PATH ? join3(REGISTRY_PATH, typeDir, item.slug) : null,
547
- remote: `${REGISTRY_URL}/${typeDir}/${item.slug}`,
608
+ local: REGISTRY_PATH ? join8(REGISTRY_PATH, typeDir2, item.slug) : null,
609
+ remote: `${REGISTRY_URL}/${typeDir2}/${item.slug}`,
548
610
  rootUrl: REGISTRY_ROOT_URL,
549
611
  revision: null
550
612
  };
@@ -560,15 +622,15 @@ async function getItemContent(item) {
560
622
  const mainFile = mainFileName(item.type);
561
623
  if (local) {
562
624
  try {
563
- return await readFile3(join3(local, mainFile), "utf-8");
625
+ return await readFile3(join8(local, mainFile), "utf-8");
564
626
  } catch {
565
627
  }
566
628
  }
567
- const tempRoot = await mkdtemp(join3(tmpdir(), "seedr-content-"));
629
+ const tempRoot = await mkdtemp(join8(tmpdir(), "seedr-content-"));
568
630
  try {
569
- const destination = join3(tempRoot, "item");
631
+ const destination = join8(tempRoot, "item");
570
632
  await fetchItemToDestination(item, destination);
571
- return await readFile3(join3(destination, mainFile), "utf-8");
633
+ return await readFile3(join8(destination, mainFile), "utf-8");
572
634
  } finally {
573
635
  await rm2(tempRoot, { recursive: true, force: true });
574
636
  }
@@ -579,7 +641,7 @@ async function fetchItemFile(item, relativePath) {
579
641
  const { local, remote } = getItemBaseUrl(item);
580
642
  if (local) {
581
643
  try {
582
- return await readFile3(join3(local, ...segments), "utf-8");
644
+ return await readFile3(join8(local, ...segments), "utf-8");
583
645
  } catch {
584
646
  }
585
647
  }
@@ -593,8 +655,8 @@ function getItemSourcePath(item) {
593
655
  return null;
594
656
  }
595
657
  assertValidSlug(item.slug);
596
- const typeDir = typeDirName(item.type);
597
- return join3(REGISTRY_PATH, typeDir, item.slug);
658
+ const typeDir2 = typeDirName(item.type);
659
+ return join8(REGISTRY_PATH, typeDir2, item.slug);
598
660
  }
599
661
  function integrityError(item, detail) {
600
662
  return new Error(`Registry integrity error: ${item.type} "${item.slug}" \u2014 ${detail}`);
@@ -639,8 +701,8 @@ async function downloadFileSet(location, fileSet, stagingDir) {
639
701
  for (const segment of segments) assertSafeNodeName(segment);
640
702
  const url = fileSet.licenseExtra && relativePath === fileSet.licenseExtra.installAs ? `${location.rootUrl}/${fileSet.licenseExtra.file}` : `${location.remote}/${relativePath}`;
641
703
  const content = await fetchRemoteBuffer(url);
642
- const filePath = join3(stagingDir, ...segments);
643
- await mkdir2(dirname2(filePath), { recursive: true });
704
+ const filePath = join8(stagingDir, ...segments);
705
+ await mkdir2(dirname4(filePath), { recursive: true });
644
706
  await writeFile2(filePath, content);
645
707
  }));
646
708
  }
@@ -650,8 +712,8 @@ async function fetchItemToDestination(item, destPath) {
650
712
  if (fileSet.digest === null && !isFirstParty(item.sourceType)) {
651
713
  throw integrityError(item, "the registry entry carries no contentDigest; refusing to install unverifiable content");
652
714
  }
653
- await mkdir2(dirname2(destPath), { recursive: true });
654
- const stagingDir = await mkdtemp(join3(dirname2(destPath), ".seedr-staging-"));
715
+ await mkdir2(dirname4(destPath), { recursive: true });
716
+ const stagingDir = await mkdtemp(join8(dirname4(destPath), ".seedr-staging-"));
655
717
  try {
656
718
  await downloadFileSet(location, fileSet, stagingDir);
657
719
  if (fileSet.digest !== null) {
@@ -670,7 +732,7 @@ async function fetchItemToDestination(item, destPath) {
670
732
 
671
733
  // src/config/agents.ts
672
734
  import { homedir as homedir2 } from "os";
673
- import { join as join4 } from "path";
735
+ import { join as join9 } from "path";
674
736
  var home = homedir2();
675
737
  var SKILL_DIRECTORY = {
676
738
  path: "skills"
@@ -679,7 +741,7 @@ var ANTIGRAVITY = {
679
741
  name: "Google Antigravity",
680
742
  shortName: "antigravity",
681
743
  projectRoot: ".agents",
682
- userRoot: join4(home, ".agents"),
744
+ userRoot: join9(home, ".agents"),
683
745
  contentTypes: { skill: SKILL_DIRECTORY }
684
746
  };
685
747
  var CODING_AGENTS = {
@@ -687,7 +749,7 @@ var CODING_AGENTS = {
687
749
  name: "Claude Code",
688
750
  shortName: "claude",
689
751
  projectRoot: ".claude",
690
- userRoot: join4(home, ".claude"),
752
+ userRoot: join9(home, ".claude"),
691
753
  contentTypes: {
692
754
  skill: SKILL_DIRECTORY,
693
755
  command: {
@@ -714,7 +776,7 @@ var CODING_AGENTS = {
714
776
  name: "GitHub Copilot",
715
777
  shortName: "copilot",
716
778
  projectRoot: ".github",
717
- userRoot: join4(home, ".github"),
779
+ userRoot: join9(home, ".github"),
718
780
  contentTypes: { skill: SKILL_DIRECTORY }
719
781
  },
720
782
  antigravity: ANTIGRAVITY,
@@ -723,14 +785,14 @@ var CODING_AGENTS = {
723
785
  name: "OpenAI Codex CLI",
724
786
  shortName: "codex",
725
787
  projectRoot: ".codex",
726
- userRoot: join4(home, ".codex"),
788
+ userRoot: join9(home, ".codex"),
727
789
  contentTypes: { skill: SKILL_DIRECTORY }
728
790
  },
729
791
  opencode: {
730
792
  name: "OpenCode",
731
793
  shortName: "opencode",
732
794
  projectRoot: ".opencode",
733
- userRoot: join4(home, ".opencode"),
795
+ userRoot: join9(home, ".opencode"),
734
796
  contentTypes: { skill: SKILL_DIRECTORY }
735
797
  }
736
798
  };
@@ -746,7 +808,7 @@ function getAgentRoot(agent, scope, cwd = process.cwd()) {
746
808
  switch (scope) {
747
809
  case "project":
748
810
  case "local":
749
- return join4(cwd, config.projectRoot);
811
+ return join9(cwd, config.projectRoot);
750
812
  case "user":
751
813
  return config.userRoot;
752
814
  }
@@ -755,27 +817,27 @@ function getContentPath(agent, type, scope, cwd = process.cwd()) {
755
817
  const typeConfig = getContentTypeConfig(agent, type);
756
818
  if (!typeConfig) return void 0;
757
819
  const root = getAgentRoot(agent, scope, cwd);
758
- return typeConfig.path ? join4(root, typeConfig.path) : root;
820
+ return typeConfig.path ? join9(root, typeConfig.path) : root;
759
821
  }
760
822
  function getSettingsPath(scope, cwd = process.cwd()) {
761
823
  switch (scope) {
762
824
  case "project":
763
- return join4(cwd, ".claude/settings.json");
825
+ return join9(cwd, ".claude/settings.json");
764
826
  case "user":
765
- return join4(home, ".claude/settings.json");
827
+ return join9(home, ".claude/settings.json");
766
828
  case "local":
767
- return join4(cwd, ".claude/settings.local.json");
829
+ return join9(cwd, ".claude/settings.local.json");
768
830
  }
769
831
  }
770
832
  function getMcpConfigPath(agent, scope, cwd = process.cwd()) {
771
833
  const isUser = scope === "user";
772
834
  switch (canonicalAgent(agent) ?? agent) {
773
835
  case "claude":
774
- return isUser ? join4(home, ".claude.json") : join4(cwd, ".mcp.json");
836
+ return isUser ? join9(home, ".claude.json") : join9(cwd, ".mcp.json");
775
837
  case "codex":
776
- return isUser ? join4(home, ".codex", "config.toml") : join4(cwd, ".codex", "config.toml");
838
+ return isUser ? join9(home, ".codex", "config.toml") : join9(cwd, ".codex", "config.toml");
777
839
  case "opencode":
778
- return isUser ? join4(home, ".config", "opencode", "opencode.json") : join4(cwd, "opencode.json");
840
+ return isUser ? join9(home, ".config", "opencode", "opencode.json") : join9(cwd, "opencode.json");
779
841
  default:
780
842
  throw new Error(`${agent} has no verified MCP configuration format`);
781
843
  }
@@ -954,7 +1016,7 @@ function error(message) {
954
1016
  }
955
1017
 
956
1018
  // src/handlers/skill.ts
957
- import { relative as relative2, dirname as dirname3 } from "path";
1019
+ import { relative as relative4, dirname as dirname5 } from "path";
958
1020
  import { homedir as homedir3 } from "os";
959
1021
  import { readdir as readdir2, symlink as symlink2 } from "fs/promises";
960
1022
  import chalk2 from "chalk";
@@ -965,18 +1027,18 @@ function getScopeRoot(scope, cwd) {
965
1027
  return scope === "user" ? homedir3() : cwd;
966
1028
  }
967
1029
  function centralSkillsDir(scope, cwd) {
968
- return dirname3(getAgentsPath("skill", "any-slug", scope, cwd));
1030
+ return dirname5(getAgentsPath("skill", "any-slug", scope, cwd));
969
1031
  }
970
1032
  async function resolveCentralPath(slug, scope, cwd) {
971
1033
  const scopeRoot = getScopeRoot(scope, cwd);
972
1034
  const centralDir = centralSkillsDir(scope, cwd);
973
- return resolveContained(scopeRoot, relative2(scopeRoot, centralDir), slug);
1035
+ return resolveContained(scopeRoot, relative4(scopeRoot, centralDir), slug);
974
1036
  }
975
1037
  async function resolveAgentSkillPath(agent, slug, scope, cwd) {
976
1038
  const destDir = getContentPath(agent, "skill", scope, cwd);
977
1039
  if (!destDir) return null;
978
1040
  const scopeRoot = getScopeRoot(scope, cwd);
979
- return resolveContained(scopeRoot, relative2(scopeRoot, destDir), slug);
1041
+ return resolveContained(scopeRoot, relative4(scopeRoot, destDir), slug);
980
1042
  }
981
1043
  async function installToCentralLocation(item, sourcePath, scope, force, cwd) {
982
1044
  const centralPath = await resolveCentralPath(item.slug, scope, cwd);
@@ -990,9 +1052,9 @@ async function installToCentralLocation(item, sourcePath, scope, force, cwd) {
990
1052
  return { centralPath, created: !existed };
991
1053
  }
992
1054
  async function createAgentSymlink(centralPath, destPath) {
993
- await ensureDir(dirname3(destPath));
1055
+ await ensureDir(dirname5(destPath));
994
1056
  await removePathEntry(destPath);
995
- const relPath = relative2(dirname3(destPath), centralPath);
1057
+ const relPath = relative4(dirname5(destPath), centralPath);
996
1058
  await symlink2(relPath, destPath);
997
1059
  }
998
1060
  async function installSkillForAgent(item, agent, scope, method, force, cwd, centralPath) {
@@ -1148,8 +1210,9 @@ export {
1148
1210
  loadManifest,
1149
1211
  getItem,
1150
1212
  getItemsBySlug,
1151
- listItems,
1213
+ listItems2 as listItems,
1152
1214
  searchItems,
1215
+ mainFileName,
1153
1216
  getItemContent,
1154
1217
  fetchItemFile,
1155
1218
  getItemSourcePath,
package/dist/cli.js CHANGED
@@ -35,6 +35,7 @@ import {
35
35
  isLegacyAgent,
36
36
  isValidSlug,
37
37
  listItems,
38
+ mainFileName,
38
39
  moveDirectory,
39
40
  outro,
40
41
  p,
@@ -56,14 +57,14 @@ import {
56
57
  warn,
57
58
  writeFileAtomic,
58
59
  writeTextFile
59
- } from "./chunk-JTCNXHYF.js";
60
+ } from "./chunk-XNSAC6CK.js";
60
61
 
61
62
  // src/cli.ts
62
63
  import { Command as Command5 } from "commander";
63
64
 
64
65
  // src/commands/add.ts
65
66
  import { Command } from "commander";
66
- import chalk7 from "chalk";
67
+ import chalk8 from "chalk";
67
68
 
68
69
  // src/handlers/registry.ts
69
70
  var handlers = /* @__PURE__ */ new Map();
@@ -143,7 +144,7 @@ function isTelemetryDisabled(env = process.env) {
143
144
  return env[TELEMETRY_OPT_OUT_VARIABLE] !== void 0;
144
145
  }
145
146
  function cliVersion() {
146
- return true ? "0.1.91" : "dev";
147
+ return true ? "0.1.92" : "dev";
147
148
  }
148
149
  async function sendEvent(event) {
149
150
  try {
@@ -218,7 +219,7 @@ async function installAgentForCodingAgent(item, agent, scope, method, force, cwd
218
219
  }
219
220
  await assertOverwritable(destPath, force);
220
221
  const sourcePath = getItemSourcePath(item);
221
- const sourceFile = sourcePath ? join(sourcePath, "AGENT.md") : null;
222
+ const sourceFile = sourcePath ? join(sourcePath, mainFileName("agent")) : null;
222
223
  if (method === "symlink" && sourceFile && await exists(sourceFile)) {
223
224
  await installFile(sourceFile, destPath, "symlink");
224
225
  } else {
@@ -278,12 +279,12 @@ async function planAgent(item, agents, scope, method, cwd) {
278
279
  const destPath = await resolveAgentFilePath(agent, item.slug, scope, cwd);
279
280
  if (!destPath) throw new Error(`${CODING_AGENTS[agent].name} does not support agents`);
280
281
  const sourcePath = getItemSourcePath(item);
281
- const linked = method === "symlink" && sourcePath !== null && await exists(join(sourcePath, "AGENT.md"));
282
+ const linked = method === "symlink" && sourcePath !== null && await exists(join(sourcePath, mainFileName("agent")));
282
283
  changes.push({
283
284
  agent,
284
285
  kind: await exists(destPath) ? "modify" : "create",
285
286
  path: destPath,
286
- detail: linked ? `symlink \u2192 ${join(sourcePath, "AGENT.md")}` : "agent definition file"
287
+ detail: linked ? `symlink \u2192 ${join(sourcePath, mainFileName("agent"))}` : "agent definition file"
287
288
  });
288
289
  }
289
290
  return changes;
@@ -302,12 +303,121 @@ var agentHandler = {
302
303
  plan: planAgent
303
304
  };
304
305
 
305
- // src/handlers/hook.ts
306
- import { join as join2, basename, dirname as dirname2 } from "path";
306
+ // src/handlers/command.ts
307
+ import { join as join2, relative as relative2 } from "path";
307
308
  import { homedir as homedir2 } from "os";
308
- import { lstat as lstat2, mkdir, mkdtemp, readFile as readFile2, realpath, rm, unlink as unlink2 } from "fs/promises";
309
+ import { lstat as lstat2, readdir as readdir2, unlink as unlink2 } from "fs/promises";
309
310
  import chalk3 from "chalk";
310
311
  import ora2 from "ora";
312
+ var SLUG_LABEL2 = "command slug";
313
+ async function resolveCommandFilePath(agent, slug, scope, cwd) {
314
+ const destDir = getContentPath(agent, "command", scope, cwd);
315
+ if (!destDir) return null;
316
+ const scopeRoot = scope === "user" ? homedir2() : cwd;
317
+ return resolveContained(scopeRoot, relative2(scopeRoot, destDir), `${slug}.md`);
318
+ }
319
+ async function installCommandForCodingAgent(item, agent, scope, method, force, cwd) {
320
+ const spinner = ora2(
321
+ `Installing ${item.name} for ${CODING_AGENTS[agent].name}...`
322
+ ).start();
323
+ try {
324
+ assertValidSlug(item.slug, SLUG_LABEL2);
325
+ const destPath = await resolveCommandFilePath(agent, item.slug, scope, cwd);
326
+ if (!destPath) {
327
+ throw new Error(`${CODING_AGENTS[agent].name} does not support commands`);
328
+ }
329
+ await assertOverwritable(destPath, force);
330
+ const sourcePath = getItemSourcePath(item);
331
+ const sourceFile = sourcePath ? join2(sourcePath, mainFileName("command")) : null;
332
+ if (method === "symlink" && sourceFile && await exists(sourceFile)) {
333
+ await installFile(sourceFile, destPath, "symlink");
334
+ } else {
335
+ const content = await getItemContent(item);
336
+ await ensureDir(getContentPath(agent, "command", scope, cwd));
337
+ await writeTextFile(destPath, content);
338
+ }
339
+ spinner.succeed(
340
+ brand(`Installed ${item.name} for ${CODING_AGENTS[agent].name}`)
341
+ );
342
+ return { agent, success: true, path: destPath };
343
+ } catch (error2) {
344
+ const errorMsg = error2 instanceof Error ? error2.message : "Unknown error";
345
+ spinner.fail(
346
+ chalk3.red(`Failed to install for ${CODING_AGENTS[agent].name}: ${errorMsg}`)
347
+ );
348
+ return { agent, success: false, path: "", error: errorMsg };
349
+ }
350
+ }
351
+ async function installCommand(item, agents, scope, method, force, cwd = process.cwd()) {
352
+ const results = [];
353
+ for (const agent of agents) {
354
+ const result = await installCommandForCodingAgent(item, agent, scope, method, force, cwd);
355
+ results.push(result);
356
+ }
357
+ return results;
358
+ }
359
+ async function uninstallCommand(slug, agent, scope, cwd = process.cwd()) {
360
+ assertValidSlug(slug, SLUG_LABEL2);
361
+ const destPath = await resolveCommandFilePath(agent, slug, scope, cwd);
362
+ if (!destPath) return false;
363
+ let stats;
364
+ try {
365
+ stats = await lstat2(destPath);
366
+ } catch (error2) {
367
+ if (error2.code === "ENOENT") return false;
368
+ throw error2;
369
+ }
370
+ if (stats.isDirectory()) {
371
+ throw new Error(`${destPath} is a directory; refusing to remove it`);
372
+ }
373
+ await unlink2(destPath);
374
+ return true;
375
+ }
376
+ async function getInstalledCommands(agent, scope, cwd = process.cwd()) {
377
+ const destDir = getContentPath(agent, "command", scope, cwd);
378
+ if (!destDir || !await exists(destDir)) {
379
+ return [];
380
+ }
381
+ const files = await readdir2(destDir);
382
+ return files.filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", ""));
383
+ }
384
+ async function planCommand(item, agents, scope, method, cwd) {
385
+ assertValidSlug(item.slug, SLUG_LABEL2);
386
+ const changes = [];
387
+ for (const agent of agents) {
388
+ const destPath = await resolveCommandFilePath(agent, item.slug, scope, cwd);
389
+ if (!destPath) throw new Error(`${CODING_AGENTS[agent].name} does not support commands`);
390
+ const sourcePath = getItemSourcePath(item);
391
+ const linked = method === "symlink" && sourcePath !== null && await exists(join2(sourcePath, mainFileName("command")));
392
+ changes.push({
393
+ agent,
394
+ kind: await exists(destPath) ? "modify" : "create",
395
+ path: destPath,
396
+ detail: linked ? `symlink \u2192 ${join2(sourcePath, mainFileName("command"))}` : "slash command file"
397
+ });
398
+ }
399
+ return changes;
400
+ }
401
+ var commandHandler = {
402
+ type: "command",
403
+ async install(item, agents, scope, method, force, cwd) {
404
+ return installCommand(item, agents, scope, method, force, cwd);
405
+ },
406
+ async uninstall(slug, agent, scope, cwd) {
407
+ return uninstallCommand(slug, agent, scope, cwd);
408
+ },
409
+ async listInstalled(agent, scope, cwd) {
410
+ return getInstalledCommands(agent, scope, cwd);
411
+ },
412
+ plan: planCommand
413
+ };
414
+
415
+ // src/handlers/hook.ts
416
+ import { join as join3, basename, dirname as dirname2 } from "path";
417
+ import { homedir as homedir3 } from "os";
418
+ import { lstat as lstat3, mkdir, mkdtemp, readFile as readFile2, realpath, rm, unlink as unlink3 } from "fs/promises";
419
+ import chalk4 from "chalk";
420
+ import ora3 from "ora";
311
421
 
312
422
  // src/utils/json.ts
313
423
  import { readFile, stat } from "fs/promises";
@@ -361,10 +471,10 @@ var CLAUDE_ONLY_ERROR = "Hooks are only supported for Claude Code";
361
471
  var SCRIPT_NAME_LABEL = "hook script name";
362
472
  var SCRIPT_MODE = 493;
363
473
  function getScopeRoot(scope, cwd) {
364
- return scope === "user" ? homedir2() : cwd;
474
+ return scope === "user" ? homedir3() : cwd;
365
475
  }
366
476
  function getHooksDir(scope, cwd) {
367
- return join2(getScopeRoot(scope, cwd), ".claude", "hooks");
477
+ return join3(getScopeRoot(scope, cwd), ".claude", "hooks");
368
478
  }
369
479
  function getScriptPath(scope, scriptName) {
370
480
  switch (scope) {
@@ -395,7 +505,7 @@ async function prepareHooksDir(scope, cwd) {
395
505
  async function assertRegularFileOrMissing(path) {
396
506
  let stats;
397
507
  try {
398
- stats = await lstat2(path);
508
+ stats = await lstat3(path);
399
509
  } catch (error2) {
400
510
  if (error2.code === "ENOENT") return;
401
511
  throw error2;
@@ -410,13 +520,13 @@ async function assertRegularFileOrMissing(path) {
410
520
  async function loadScriptBytes(item, scriptFile, hooksDir) {
411
521
  const sourcePath = getItemSourcePath(item);
412
522
  if (sourcePath && await exists(sourcePath)) {
413
- return readFile2(join2(sourcePath, scriptFile));
523
+ return readFile2(join3(sourcePath, scriptFile));
414
524
  }
415
- const fetchDir = await mkdtemp(join2(dirname2(hooksDir), ".seedr-hook-"));
525
+ const fetchDir = await mkdtemp(join3(dirname2(hooksDir), ".seedr-hook-"));
416
526
  try {
417
- const contentDir = join2(fetchDir, "content");
527
+ const contentDir = join3(fetchDir, "content");
418
528
  await fetchItemToDestination(item, contentDir);
419
- return await readFile2(join2(contentDir, scriptFile));
529
+ return await readFile2(join3(contentDir, scriptFile));
420
530
  } finally {
421
531
  await rm(fetchDir, { recursive: true, force: true });
422
532
  }
@@ -438,7 +548,7 @@ function mergeTriggers(hooks, triggers, command) {
438
548
  }
439
549
  }
440
550
  async function installHookForAgent(item, agent, scope, _method, force, cwd) {
441
- const spinner = ora2(
551
+ const spinner = ora3(
442
552
  `Installing ${item.name} for ${CODING_AGENTS[agent].name}...`
443
553
  ).start();
444
554
  try {
@@ -478,7 +588,7 @@ async function installHookForAgent(item, agent, scope, _method, force, cwd) {
478
588
  } catch (error2) {
479
589
  const errorMsg = error2 instanceof Error ? error2.message : "Unknown error";
480
590
  spinner.fail(
481
- chalk3.red(`Failed to install for ${CODING_AGENTS[agent].name}: ${errorMsg}`)
591
+ chalk4.red(`Failed to install for ${CODING_AGENTS[agent].name}: ${errorMsg}`)
482
592
  );
483
593
  return { agent, success: false, path: "", error: errorMsg };
484
594
  }
@@ -519,7 +629,7 @@ async function removeScriptFile(scope, cwd, scriptFileName) {
519
629
  const scriptFilePath = await resolveContained(hooksDir, scriptFileName);
520
630
  let stats;
521
631
  try {
522
- stats = await lstat2(scriptFilePath);
632
+ stats = await lstat3(scriptFilePath);
523
633
  } catch (error2) {
524
634
  if (error2.code === "ENOENT") return false;
525
635
  throw error2;
@@ -527,7 +637,7 @@ async function removeScriptFile(scope, cwd, scriptFileName) {
527
637
  if (stats.isDirectory()) {
528
638
  throw new Error(`${scriptFilePath} is a directory; refusing to remove it`);
529
639
  }
530
- await unlink2(scriptFilePath);
640
+ await unlink3(scriptFilePath);
531
641
  return true;
532
642
  }
533
643
  async function uninstallHook(slug, agent, scope, cwd = process.cwd()) {
@@ -608,8 +718,8 @@ var hookHandler = {
608
718
  // src/handlers/mcp.ts
609
719
  import { readFile as readFile3 } from "fs/promises";
610
720
  import { dirname as dirname3 } from "path";
611
- import chalk4 from "chalk";
612
- import ora3 from "ora";
721
+ import chalk5 from "chalk";
722
+ import ora4 from "ora";
613
723
 
614
724
  // src/utils/toml.ts
615
725
  var BARE_KEY_PATTERN = /^[A-Za-z0-9_-]+$/;
@@ -944,7 +1054,7 @@ function adapterFor(agent) {
944
1054
  return adapter;
945
1055
  }
946
1056
  async function installMcpForAgent(item, agent, scope, _method, force, cwd) {
947
- const spinner = ora3(
1057
+ const spinner = ora4(
948
1058
  `Installing ${item.name} for ${CODING_AGENTS[agent].name}...`
949
1059
  ).start();
950
1060
  try {
@@ -964,7 +1074,7 @@ async function installMcpForAgent(item, agent, scope, _method, force, cwd) {
964
1074
  } catch (error2) {
965
1075
  const errorMsg = error2 instanceof Error ? error2.message : "Unknown error";
966
1076
  spinner.fail(
967
- chalk4.red(`Failed to install for ${CODING_AGENTS[agent].name}: ${errorMsg}`)
1077
+ chalk5.red(`Failed to install for ${CODING_AGENTS[agent].name}: ${errorMsg}`)
968
1078
  );
969
1079
  return { agent, success: false, path: "", error: errorMsg };
970
1080
  }
@@ -1032,8 +1142,8 @@ var mcpHandler = {
1032
1142
  };
1033
1143
 
1034
1144
  // src/handlers/settings.ts
1035
- import chalk5 from "chalk";
1036
- import ora4 from "ora";
1145
+ import chalk6 from "chalk";
1146
+ import ora5 from "ora";
1037
1147
  var SETTINGS_NOT_DISCOVERABLE = "settings items cannot be discovered (they are merged into settings.json)";
1038
1148
  var CLAUDE_ONLY_ERROR2 = "Settings are only supported for Claude Code";
1039
1149
  function parseSettings(content) {
@@ -1044,7 +1154,7 @@ function parseSettings(content) {
1044
1154
  }
1045
1155
  }
1046
1156
  async function installSettingsForAgent(item, agent, scope, _method, _force, cwd) {
1047
- const spinner = ora4(
1157
+ const spinner = ora5(
1048
1158
  `Installing ${item.name} for ${CODING_AGENTS[agent].name}...`
1049
1159
  ).start();
1050
1160
  try {
@@ -1064,7 +1174,7 @@ async function installSettingsForAgent(item, agent, scope, _method, _force, cwd)
1064
1174
  } catch (error2) {
1065
1175
  const errorMsg = error2 instanceof Error ? error2.message : "Unknown error";
1066
1176
  spinner.fail(
1067
- chalk5.red(`Failed to install for ${CODING_AGENTS[agent].name}: ${errorMsg}`)
1177
+ chalk6.red(`Failed to install for ${CODING_AGENTS[agent].name}: ${errorMsg}`)
1068
1178
  );
1069
1179
  return { agent, success: false, path: "", error: errorMsg };
1070
1180
  }
@@ -1158,22 +1268,22 @@ var settingsHandler = {
1158
1268
  };
1159
1269
 
1160
1270
  // src/handlers/plugin.ts
1161
- import { homedir as homedir3 } from "os";
1162
- import { join as join3, relative as relative2 } from "path";
1271
+ import { homedir as homedir4 } from "os";
1272
+ import { join as join4, relative as relative3 } from "path";
1163
1273
  import { mkdir as mkdir2, mkdtemp as mkdtemp2, rm as rm2 } from "fs/promises";
1164
1274
  import { execFile } from "child_process";
1165
1275
  import { promisify } from "util";
1166
- import chalk6 from "chalk";
1167
- import ora5 from "ora";
1168
- var home = homedir3();
1169
- var PLUGINS_DIR = join3(home, ".claude", "plugins");
1170
- var PLUGINS_CACHE_DIR = join3(PLUGINS_DIR, "cache");
1171
- var INSTALLED_PLUGINS_PATH = join3(PLUGINS_DIR, "installed_plugins.json");
1172
- var KNOWN_MARKETPLACES_PATH = join3(PLUGINS_DIR, "known_marketplaces.json");
1173
- var MARKETPLACES_DIR = join3(PLUGINS_DIR, "marketplaces");
1276
+ import chalk7 from "chalk";
1277
+ import ora6 from "ora";
1278
+ var home = homedir4();
1279
+ var PLUGINS_DIR = join4(home, ".claude", "plugins");
1280
+ var PLUGINS_CACHE_DIR = join4(PLUGINS_DIR, "cache");
1281
+ var INSTALLED_PLUGINS_PATH = join4(PLUGINS_DIR, "installed_plugins.json");
1282
+ var KNOWN_MARKETPLACES_PATH = join4(PLUGINS_DIR, "known_marketplaces.json");
1283
+ var MARKETPLACES_DIR = join4(PLUGINS_DIR, "marketplaces");
1174
1284
  var PLUGIN_JSON_PATH = ".claude-plugin/plugin.json";
1175
1285
  var CLAUDE_ONLY_ERROR3 = "Plugins are only supported for Claude Code";
1176
- var SLUG_LABEL2 = "plugin slug";
1286
+ var SLUG_LABEL3 = "plugin slug";
1177
1287
  var GITHUB_REPO_SLUG_PATTERN = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
1178
1288
  function getPluginId(name, marketplace) {
1179
1289
  return `${name}@${marketplace}`;
@@ -1235,8 +1345,8 @@ async function ensureMarketplaceRegistered(marketplace, item) {
1235
1345
  async function createStagingDir(slug) {
1236
1346
  const tmpRoot = await resolveContained(PLUGINS_CACHE_DIR, ".tmp");
1237
1347
  await mkdir2(tmpRoot, { recursive: true });
1238
- const staging = await mkdtemp2(join3(tmpRoot, `${slug}-`));
1239
- return resolveContained(PLUGINS_CACHE_DIR, relative2(PLUGINS_CACHE_DIR, staging));
1348
+ const staging = await mkdtemp2(join4(tmpRoot, `${slug}-`));
1349
+ return resolveContained(PLUGINS_CACHE_DIR, relative3(PLUGINS_CACHE_DIR, staging));
1240
1350
  }
1241
1351
  async function stageContent(item, contentPath) {
1242
1352
  const sourcePath = getItemSourcePath(item);
@@ -1320,20 +1430,20 @@ async function commitInstall(params) {
1320
1430
  }
1321
1431
  }
1322
1432
  async function installPluginForAgent(item, agent, scope, _method, force, cwd) {
1323
- const spinner = ora5(
1433
+ const spinner = ora6(
1324
1434
  `Installing ${item.name} for ${CODING_AGENTS[agent].name}...`
1325
1435
  ).start();
1326
1436
  try {
1327
1437
  if (agent !== "claude") {
1328
1438
  throw new Error(CLAUDE_ONLY_ERROR3);
1329
1439
  }
1330
- assertValidSlug(item.slug, SLUG_LABEL2);
1440
+ assertValidSlug(item.slug, SLUG_LABEL3);
1331
1441
  const marketplace = resolveMarketplaceName(item);
1332
1442
  const staging = await createStagingDir(item.slug);
1333
1443
  try {
1334
- const contentPath = join3(staging, "content");
1444
+ const contentPath = join4(staging, "content");
1335
1445
  const fetched = await stageContent(item, contentPath);
1336
- const pluginJson = await readJson(join3(contentPath, ...PLUGIN_JSON_PATH.split("/")));
1446
+ const pluginJson = await readJson(join4(contentPath, ...PLUGIN_JSON_PATH.split("/")));
1337
1447
  const { name, version } = resolvePluginIdentity(item, pluginJson);
1338
1448
  const gitCommitSha = resolveGitCommitSha(item, fetched);
1339
1449
  const pluginId = getPluginId(name, marketplace);
@@ -1351,7 +1461,7 @@ async function installPluginForAgent(item, agent, scope, _method, force, cwd) {
1351
1461
  } catch (error2) {
1352
1462
  const errorMsg = error2 instanceof Error ? error2.message : "Unknown error";
1353
1463
  spinner.fail(
1354
- chalk6.red(`Failed to install for ${CODING_AGENTS[agent].name}: ${errorMsg}`)
1464
+ chalk7.red(`Failed to install for ${CODING_AGENTS[agent].name}: ${errorMsg}`)
1355
1465
  );
1356
1466
  return { agent, success: false, path: "", error: errorMsg };
1357
1467
  }
@@ -1393,7 +1503,7 @@ async function removeOrphanedCache(installPath, registry) {
1393
1503
  await removePathEntry(contained);
1394
1504
  }
1395
1505
  async function uninstallPlugin(slug, agent, scope, cwd = process.cwd()) {
1396
- assertValidSlug(slug, SLUG_LABEL2);
1506
+ assertValidSlug(slug, SLUG_LABEL3);
1397
1507
  if (agent !== "claude") return false;
1398
1508
  const registry = await readJson(INSTALLED_PLUGINS_PATH);
1399
1509
  if (!registry.plugins) return false;
@@ -1435,7 +1545,7 @@ async function getInstalledPlugins(agent, scope, cwd = process.cwd()) {
1435
1545
  async function readPluginJsonForPlan(item) {
1436
1546
  const sourcePath = getItemSourcePath(item);
1437
1547
  if (sourcePath) {
1438
- return readJson(join3(sourcePath, ...PLUGIN_JSON_PATH.split("/")));
1548
+ return readJson(join4(sourcePath, ...PLUGIN_JSON_PATH.split("/")));
1439
1549
  }
1440
1550
  return JSON.parse(await fetchItemFile(item, PLUGIN_JSON_PATH));
1441
1551
  }
@@ -1446,7 +1556,7 @@ async function planPlugin(item, agents, scope, _method, cwd) {
1446
1556
  const changes = [];
1447
1557
  for (const agent of agents) {
1448
1558
  if (agent !== "claude") throw new Error(CLAUDE_ONLY_ERROR3);
1449
- assertValidSlug(item.slug, SLUG_LABEL2);
1559
+ assertValidSlug(item.slug, SLUG_LABEL3);
1450
1560
  const marketplace = resolveMarketplaceName(item);
1451
1561
  const { name, version } = resolvePluginIdentity(item, await readPluginJsonForPlan(item));
1452
1562
  const pluginId = getPluginId(name, marketplace);
@@ -1494,6 +1604,7 @@ var pluginHandler = {
1494
1604
  // src/handlers/index.ts
1495
1605
  registerHandler(skillHandler);
1496
1606
  registerHandler(agentHandler);
1607
+ registerHandler(commandHandler);
1497
1608
  registerHandler(hookHandler);
1498
1609
  registerHandler(mcpHandler);
1499
1610
  registerHandler(settingsHandler);
@@ -1578,8 +1689,8 @@ function formatPlan(changes) {
1578
1689
  for (const [label, group] of groups) {
1579
1690
  lines.push(` ${label}:`);
1580
1691
  for (const change of group) {
1581
- const detail = change.detail ? ` ${chalk7.gray(`\u2014 ${change.detail}`)}` : "";
1582
- lines.push(` ${chalk7.gray(`[${KIND_LABEL[change.kind]}]`)} ${change.path}${detail}`);
1692
+ const detail = change.detail ? ` ${chalk8.gray(`\u2014 ${change.detail}`)}` : "";
1693
+ lines.push(` ${chalk8.gray(`[${KIND_LABEL[change.kind]}]`)} ${change.path}${detail}`);
1583
1694
  }
1584
1695
  }
1585
1696
  return lines;
@@ -1689,13 +1800,13 @@ function printInstallSummary(results) {
1689
1800
  if (successful.length > 0) {
1690
1801
  success(`Installed for ${successful.length} agent(s)`);
1691
1802
  for (const r of successful) {
1692
- console.log(chalk7.gray(` \u2192 ${r.path}`));
1803
+ console.log(chalk8.gray(` \u2192 ${r.path}`));
1693
1804
  }
1694
1805
  }
1695
1806
  if (failed.length > 0) {
1696
1807
  error(`Failed for ${failed.length} agent(s)`);
1697
1808
  for (const r of failed) {
1698
- console.log(chalk7.red(` \xD7 ${r.agent}: ${r.error}`));
1809
+ console.log(chalk8.red(` \xD7 ${r.agent}: ${r.error}`));
1699
1810
  }
1700
1811
  }
1701
1812
  return exitCode;
@@ -1709,7 +1820,7 @@ async function runAdd(name, options, cwd = process.cwd()) {
1709
1820
  const item = await resolveItem(name, options.type);
1710
1821
  if (item === CANCELLED) return 0;
1711
1822
  if (!item) return 1;
1712
- step(`Selected: ${brand(item.name)} ${chalk7.gray(`(${item.type})`)} ${chalk7.gray(`- ${item.description}`)}`);
1823
+ step(`Selected: ${brand(item.name)} ${chalk8.gray(`(${item.type})`)} ${chalk8.gray(`- ${item.description}`)}`);
1713
1824
  const handler = getHandler(item.type);
1714
1825
  if (!handler) {
1715
1826
  error(`No handler found for type "${item.type}"`);
@@ -1763,17 +1874,17 @@ Telemetry: ${TELEMETRY_HELP_TEXT}.`).action(async (name, options) => {
1763
1874
 
1764
1875
  // src/commands/list.ts
1765
1876
  import { Command as Command2 } from "commander";
1766
- import chalk8 from "chalk";
1877
+ import chalk9 from "chalk";
1767
1878
  var SEPARATOR_WIDTH = 40;
1768
1879
  var SLUG_COLUMN_WIDTH = 24;
1769
1880
  var TYPE_COLORS = {
1770
- skill: chalk8.magenta,
1771
- hook: chalk8.hex("#a855f7"),
1772
- agent: chalk8.blue,
1773
- plugin: chalk8.hex("#6366f1"),
1774
- command: chalk8.hex("#f59e0b"),
1775
- settings: chalk8.hex("#f97316"),
1776
- mcp: chalk8.hex("#2dd4bf")
1881
+ skill: chalk9.magenta,
1882
+ hook: chalk9.hex("#a855f7"),
1883
+ agent: chalk9.blue,
1884
+ plugin: chalk9.hex("#6366f1"),
1885
+ command: chalk9.hex("#f59e0b"),
1886
+ settings: chalk9.hex("#f97316"),
1887
+ mcp: chalk9.hex("#2dd4bf")
1777
1888
  };
1778
1889
  async function collectInstalledItems(params) {
1779
1890
  const types = params.types ?? getRegisteredTypes();
@@ -1802,7 +1913,7 @@ function resolveListAgents(agentsArg) {
1802
1913
  async function runList(options, cwd = process.cwd()) {
1803
1914
  const optionError = validateType(options.type) || validateScope(options.scope);
1804
1915
  if (optionError) {
1805
- console.log(chalk8.red(optionError));
1916
+ console.log(chalk9.red(optionError));
1806
1917
  return 1;
1807
1918
  }
1808
1919
  const type = options.type;
@@ -1811,7 +1922,7 @@ async function runList(options, cwd = process.cwd()) {
1811
1922
  }
1812
1923
  const agents = resolveListAgents(options.agents);
1813
1924
  if (typeof agents === "string") {
1814
- console.log(chalk8.red(agents));
1925
+ console.log(chalk9.red(agents));
1815
1926
  return 1;
1816
1927
  }
1817
1928
  const scope = options.scope ?? "project";
@@ -1831,32 +1942,32 @@ async function listAvailable(type, label) {
1831
1942
  const items = label ? all.filter((item) => item.label === label) : all;
1832
1943
  if (items.length === 0 && label) {
1833
1944
  const known = [...new Set(all.map((item) => item.label).filter(Boolean))].sort();
1834
- console.log(chalk8.red(`No item carries the label "${label}".`));
1835
- if (known.length > 0) console.log(chalk8.gray(`Labels in use: ${known.join(", ")}`));
1945
+ console.log(chalk9.red(`No item carries the label "${label}".`));
1946
+ if (known.length > 0) console.log(chalk9.gray(`Labels in use: ${known.join(", ")}`));
1836
1947
  return 1;
1837
1948
  }
1838
1949
  if (items.length === 0) {
1839
- console.log(chalk8.yellow("No items found in registry"));
1950
+ console.log(chalk9.yellow("No items found in registry"));
1840
1951
  return 0;
1841
1952
  }
1842
1953
  const grouped = groupByType(items);
1843
1954
  for (const [itemType, typeItems] of Object.entries(grouped)) {
1844
- const colorFn = TYPE_COLORS[itemType] ?? chalk8.white;
1955
+ const colorFn = TYPE_COLORS[itemType] ?? chalk9.white;
1845
1956
  console.log(colorFn(`
1846
1957
  ${itemType.toUpperCase()}S`));
1847
- console.log(chalk8.gray("\u2500".repeat(SEPARATOR_WIDTH)));
1958
+ console.log(chalk9.gray("\u2500".repeat(SEPARATOR_WIDTH)));
1848
1959
  for (const item of typeItems) {
1849
1960
  const compatIcons = [...new Set(item.compatibility.map((a) => CODING_AGENTS[a]?.shortName ?? a))].join(" ");
1850
- const featured = item.featured ? chalk8.yellow("\u2605 ") : " ";
1961
+ const featured = item.featured ? chalk9.yellow("\u2605 ") : " ";
1851
1962
  console.log(
1852
- `${featured}${chalk8.white(item.slug.padEnd(SLUG_COLUMN_WIDTH))} ${chalk8.gray(compatIcons)}`
1963
+ `${featured}${chalk9.white(item.slug.padEnd(SLUG_COLUMN_WIDTH))} ${chalk9.gray(compatIcons)}`
1853
1964
  );
1854
- console.log(` ${chalk8.gray(item.description)}`);
1965
+ console.log(` ${chalk9.gray(item.description)}`);
1855
1966
  }
1856
1967
  }
1857
1968
  console.log("");
1858
1969
  console.log(
1859
- chalk8.gray(`Total: ${items.length} items. Use 'npx @danieldeusing/seedr add <name>' to install.`)
1970
+ chalk9.gray(`Total: ${items.length} items. Use 'npx @danieldeusing/seedr add <name>' to install.`)
1860
1971
  );
1861
1972
  return 0;
1862
1973
  }
@@ -1870,23 +1981,23 @@ Installed items (${params.scope} scope):
1870
1981
  for (const group of groups) {
1871
1982
  if (group.type !== currentType) {
1872
1983
  currentType = group.type;
1873
- const colorFn = TYPE_COLORS[group.type] ?? chalk8.white;
1984
+ const colorFn = TYPE_COLORS[group.type] ?? chalk9.white;
1874
1985
  console.log(colorFn(`${group.type.toUpperCase()}S`));
1875
1986
  }
1876
- console.log(chalk8.blue(` ${CODING_AGENTS[group.agent].name}`));
1987
+ console.log(chalk9.blue(` ${CODING_AGENTS[group.agent].name}`));
1877
1988
  for (const slug of group.slugs) {
1878
- console.log(` ${chalk8.white(slug)}`);
1989
+ console.log(` ${chalk9.white(slug)}`);
1879
1990
  total++;
1880
1991
  }
1881
1992
  console.log("");
1882
1993
  }
1883
1994
  if (!params.types || params.types.includes("settings")) {
1884
- console.log(chalk8.gray(`Note: ${SETTINGS_NOT_DISCOVERABLE}`));
1995
+ console.log(chalk9.gray(`Note: ${SETTINGS_NOT_DISCOVERABLE}`));
1885
1996
  }
1886
1997
  if (total === 0) {
1887
- console.log(chalk8.yellow("No items installed"));
1998
+ console.log(chalk9.yellow("No items installed"));
1888
1999
  } else {
1889
- console.log(chalk8.gray(`Total: ${total} installed`));
2000
+ console.log(chalk9.gray(`Total: ${total} installed`));
1890
2001
  }
1891
2002
  }
1892
2003
  function groupByType(items) {
@@ -1904,8 +2015,8 @@ function groupByType(items) {
1904
2015
 
1905
2016
  // src/commands/remove.ts
1906
2017
  import { Command as Command3 } from "commander";
1907
- import chalk9 from "chalk";
1908
- import ora6 from "ora";
2018
+ import chalk10 from "chalk";
2019
+ import ora7 from "ora";
1909
2020
  async function findInstalledAgents(slug, type, scope, cwd) {
1910
2021
  const handler = getHandler(type);
1911
2022
  if (!handler) return [];
@@ -1923,13 +2034,13 @@ async function removeFromAgents(slug, type, agents, scope, cwd) {
1923
2034
  if (!handler) return 0;
1924
2035
  let successCount = 0;
1925
2036
  for (const agent of agents) {
1926
- const spinner = ora6(`Removing from ${CODING_AGENTS[agent].name}...`).start();
2037
+ const spinner = ora7(`Removing from ${CODING_AGENTS[agent].name}...`).start();
1927
2038
  const removed = await handler.uninstall(slug, agent, scope, cwd);
1928
2039
  if (removed) {
1929
2040
  spinner.succeed(brand(`Removed from ${CODING_AGENTS[agent].name}`));
1930
2041
  successCount++;
1931
2042
  } else {
1932
- spinner.info(chalk9.gray(`Not found in ${CODING_AGENTS[agent].name}`));
2043
+ spinner.info(chalk10.gray(`Not found in ${CODING_AGENTS[agent].name}`));
1933
2044
  }
1934
2045
  }
1935
2046
  return successCount;
@@ -1954,14 +2065,14 @@ function validateRemoveRequest(name, options) {
1954
2065
  async function runRemove(name, options, cwd = process.cwd()) {
1955
2066
  const requestError = validateRemoveRequest(name, options);
1956
2067
  if (requestError) {
1957
- console.log(chalk9.red(requestError));
2068
+ console.log(chalk10.red(requestError));
1958
2069
  return 1;
1959
2070
  }
1960
2071
  const scope = options.scope ?? "project";
1961
2072
  const type = options.type;
1962
2073
  const handler = getHandler(type);
1963
2074
  if (!handler) {
1964
- console.log(chalk9.red(`No handler found for type "${type}"`));
2075
+ console.log(chalk10.red(`No handler found for type "${type}"`));
1965
2076
  return 1;
1966
2077
  }
1967
2078
  let agents;
@@ -1974,11 +2085,11 @@ async function runRemove(name, options, cwd = process.cwd()) {
1974
2085
  }
1975
2086
  if (agents.length === 0) {
1976
2087
  if (type === "settings") {
1977
- console.log(chalk9.yellow(`Cannot detect where "${name}" is installed: ${SETTINGS_NOT_DISCOVERABLE}`));
1978
- console.log(chalk9.gray("Name the agents explicitly, e.g. --agents claude"));
2088
+ console.log(chalk10.yellow(`Cannot detect where "${name}" is installed: ${SETTINGS_NOT_DISCOVERABLE}`));
2089
+ console.log(chalk10.gray("Name the agents explicitly, e.g. --agents claude"));
1979
2090
  return 1;
1980
2091
  }
1981
- console.log(chalk9.yellow(`${type} "${name}" is not installed in ${scope} scope`));
2092
+ console.log(chalk10.yellow(`${type} "${name}" is not installed in ${scope} scope`));
1982
2093
  return 0;
1983
2094
  }
1984
2095
  if (!options.yes) {
@@ -1991,7 +2102,7 @@ Will remove ${type} "${name}" from:`));
1991
2102
  const answer = await confirm("Proceed with removal?");
1992
2103
  const confirmed = !p.isCancel(answer) && answer;
1993
2104
  if (!confirmed) {
1994
- console.log(chalk9.yellow("Removal cancelled"));
2105
+ console.log(chalk10.yellow("Removal cancelled"));
1995
2106
  return 0;
1996
2107
  }
1997
2108
  }
@@ -2001,7 +2112,7 @@ Will remove ${type} "${name}" from:`));
2001
2112
  console.log(brand(`Successfully removed from ${successCount} agent(s)`));
2002
2113
  return 0;
2003
2114
  }
2004
- console.log(chalk9.yellow("Nothing to remove"));
2115
+ console.log(chalk10.yellow("Nothing to remove"));
2005
2116
  return 0;
2006
2117
  }
2007
2118
  var removeCommand = new Command3("remove").alias("rm").description("Remove an installed item (skill, plugin, agent, hook, mcp)").argument("<name>", "Name/slug of the item to remove").option("-t, --type <type>", "Content type: skill, agent, hook, mcp, plugin, settings").option(
@@ -2022,9 +2133,9 @@ var removeCommand = new Command3("remove").alias("rm").description("Remove an in
2022
2133
 
2023
2134
  // src/commands/init.ts
2024
2135
  import { Command as Command4 } from "commander";
2025
- import chalk10 from "chalk";
2026
- import ora7 from "ora";
2027
- import { join as join4 } from "path";
2136
+ import chalk11 from "chalk";
2137
+ import ora8 from "ora";
2138
+ import { join as join5 } from "path";
2028
2139
  function readmeFor(agent) {
2029
2140
  return `# ${CODING_AGENTS[agent].name} Configuration
2030
2141
 
@@ -2042,7 +2153,7 @@ async function initializeAgent(agent, cwd) {
2042
2153
  const path = getAgentPath(agent, "project", cwd);
2043
2154
  if (await exists(path)) return false;
2044
2155
  await ensureDir(path);
2045
- await writeTextFile(join4(path, "README.md"), readmeFor(agent));
2156
+ await writeTextFile(join5(path, "README.md"), readmeFor(agent));
2046
2157
  return true;
2047
2158
  }
2048
2159
  async function runInit(options, cwd = process.cwd()) {
@@ -2053,13 +2164,13 @@ async function runInit(options, cwd = process.cwd()) {
2053
2164
  } else {
2054
2165
  const parsed = parseAgentsArgStrict(agentsArg);
2055
2166
  if (parsed.unknown.length > 0) {
2056
- console.error(chalk10.red(`Unknown agent(s): ${parsed.unknown.join(", ")}. Valid agents: ${ALL_AGENTS.join(", ")} or "all"`));
2167
+ console.error(chalk11.red(`Unknown agent(s): ${parsed.unknown.join(", ")}. Valid agents: ${ALL_AGENTS.join(", ")} or "all"`));
2057
2168
  return 1;
2058
2169
  }
2059
2170
  agents = parsed.agents;
2060
2171
  }
2061
2172
  if (agents.length === 0) {
2062
- console.error(chalk10.red("No valid agents specified"));
2173
+ console.error(chalk11.red("No valid agents specified"));
2063
2174
  return 1;
2064
2175
  }
2065
2176
  console.log(brand("\nWill initialize configuration for:"));
@@ -2071,16 +2182,16 @@ async function runInit(options, cwd = process.cwd()) {
2071
2182
  const answer = await confirm("Proceed?");
2072
2183
  const confirmed = !p.isCancel(answer) && answer;
2073
2184
  if (!confirmed) {
2074
- console.log(chalk10.yellow("Cancelled"));
2185
+ console.log(chalk11.yellow("Cancelled"));
2075
2186
  return 0;
2076
2187
  }
2077
2188
  }
2078
2189
  for (const agent of agents) {
2079
- const spinner = ora7(`Initializing ${CODING_AGENTS[agent].name}...`).start();
2190
+ const spinner = ora8(`Initializing ${CODING_AGENTS[agent].name}...`).start();
2080
2191
  if (await initializeAgent(agent, cwd)) {
2081
2192
  spinner.succeed(brand(`Initialized ${CODING_AGENTS[agent].name}`));
2082
2193
  } else {
2083
- spinner.info(chalk10.gray(`${CODING_AGENTS[agent].name} already initialized`));
2194
+ spinner.info(chalk11.gray(`${CODING_AGENTS[agent].name} already initialized`));
2084
2195
  }
2085
2196
  }
2086
2197
  console.log("");
@@ -2103,7 +2214,7 @@ var initCommand = new Command4("init").description("Initialize coding agent conf
2103
2214
  // package.json
2104
2215
  var package_default = {
2105
2216
  name: "@danieldeusing/seedr",
2106
- version: "0.1.91",
2217
+ version: "0.1.92",
2107
2218
  description: "Seed your projects with AI configurations",
2108
2219
  type: "module",
2109
2220
  bin: {
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  loadManifest,
16
16
  searchItems,
17
17
  uninstallSkill
18
- } from "./chunk-JTCNXHYF.js";
18
+ } from "./chunk-XNSAC6CK.js";
19
19
  export {
20
20
  ALL_AGENTS,
21
21
  CODING_AGENTS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danieldeusing/seedr",
3
- "version": "0.1.91",
3
+ "version": "0.1.92",
4
4
  "description": "Seed your projects with AI configurations",
5
5
  "type": "module",
6
6
  "bin": {