@toolr/seedr 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +113 -29
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -248,6 +248,8 @@ var agentHandler = {
|
|
|
248
248
|
};
|
|
249
249
|
|
|
250
250
|
// src/handlers/hook.ts
|
|
251
|
+
import { join as join2 } from "path";
|
|
252
|
+
import { mkdir, copyFile, chmod } from "fs/promises";
|
|
251
253
|
import chalk4 from "chalk";
|
|
252
254
|
import ora2 from "ora";
|
|
253
255
|
|
|
@@ -283,14 +285,35 @@ function deepMerge(target, source) {
|
|
|
283
285
|
}
|
|
284
286
|
|
|
285
287
|
// src/handlers/hook.ts
|
|
286
|
-
function
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
288
|
+
function getHooksDir(scope, cwd) {
|
|
289
|
+
switch (scope) {
|
|
290
|
+
case "user":
|
|
291
|
+
return join2(process.env.HOME || "~", ".claude", "hooks");
|
|
292
|
+
case "project":
|
|
293
|
+
case "local":
|
|
294
|
+
return join2(cwd, ".claude", "hooks");
|
|
291
295
|
}
|
|
292
296
|
}
|
|
293
|
-
|
|
297
|
+
function getScriptPath(scope, scriptName) {
|
|
298
|
+
switch (scope) {
|
|
299
|
+
case "user":
|
|
300
|
+
return `~/.claude/hooks/${scriptName}`;
|
|
301
|
+
case "project":
|
|
302
|
+
case "local":
|
|
303
|
+
return `.claude/hooks/${scriptName}`;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function findScriptFile(item) {
|
|
307
|
+
const files = item.contents?.files;
|
|
308
|
+
if (!files) return null;
|
|
309
|
+
for (const file of files) {
|
|
310
|
+
if (file.type === "file" && file.name.endsWith(".sh")) {
|
|
311
|
+
return file.name;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
async function installHookForTool(item, tool, scope, method, cwd) {
|
|
294
317
|
const spinner = ora2(
|
|
295
318
|
`Installing ${item.name} for ${AI_TOOLS[tool].name}...`
|
|
296
319
|
).start();
|
|
@@ -298,19 +321,65 @@ async function installHookForTool(item, tool, scope, _method, cwd) {
|
|
|
298
321
|
if (tool !== "claude") {
|
|
299
322
|
throw new Error("Hooks are only supported for Claude Code");
|
|
300
323
|
}
|
|
301
|
-
const
|
|
302
|
-
|
|
324
|
+
const triggers = item.contents?.triggers;
|
|
325
|
+
if (!triggers || triggers.length === 0) {
|
|
326
|
+
throw new Error("No triggers defined for this hook");
|
|
327
|
+
}
|
|
328
|
+
const scriptFile = findScriptFile(item);
|
|
329
|
+
if (!scriptFile) {
|
|
330
|
+
throw new Error("No script file found in hook");
|
|
331
|
+
}
|
|
332
|
+
const hooksDir = getHooksDir(scope, cwd);
|
|
333
|
+
await mkdir(hooksDir, { recursive: true });
|
|
334
|
+
const sourcePath = getItemSourcePath(item);
|
|
335
|
+
const destScriptPath = join2(hooksDir, scriptFile);
|
|
336
|
+
if (sourcePath && await exists(sourcePath)) {
|
|
337
|
+
const sourceScriptPath = join2(sourcePath, scriptFile);
|
|
338
|
+
await copyFile(sourceScriptPath, destScriptPath);
|
|
339
|
+
} else {
|
|
340
|
+
const tempDir = join2(cwd, ".claude", ".tmp", item.slug);
|
|
341
|
+
await fetchItemToDestination(item, tempDir);
|
|
342
|
+
await copyFile(join2(tempDir, scriptFile), destScriptPath);
|
|
343
|
+
const { rm } = await import("fs/promises");
|
|
344
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
345
|
+
}
|
|
346
|
+
await chmod(destScriptPath, 493);
|
|
303
347
|
const settingsPath = getSettingsPath(scope, cwd);
|
|
304
348
|
const settings = await readJson(settingsPath);
|
|
305
349
|
settings.hooks = settings.hooks || {};
|
|
306
|
-
const
|
|
307
|
-
const
|
|
308
|
-
|
|
350
|
+
const scriptPath = getScriptPath(scope, scriptFile);
|
|
351
|
+
for (const trigger of triggers) {
|
|
352
|
+
const event = trigger.event;
|
|
353
|
+
const matcher = trigger.matcher;
|
|
354
|
+
if (!settings.hooks[event]) {
|
|
355
|
+
settings.hooks[event] = [];
|
|
356
|
+
}
|
|
357
|
+
const existingEntry = settings.hooks[event].find(
|
|
358
|
+
(e) => e.matcher === matcher
|
|
359
|
+
);
|
|
360
|
+
const hookCommand = { type: "command", command: scriptPath };
|
|
361
|
+
if (existingEntry) {
|
|
362
|
+
const alreadyExists = existingEntry.hooks.some(
|
|
363
|
+
(h) => h.command === scriptPath
|
|
364
|
+
);
|
|
365
|
+
if (!alreadyExists) {
|
|
366
|
+
existingEntry.hooks.push(hookCommand);
|
|
367
|
+
}
|
|
368
|
+
} else {
|
|
369
|
+
const newEntry = {
|
|
370
|
+
hooks: [hookCommand]
|
|
371
|
+
};
|
|
372
|
+
if (matcher) {
|
|
373
|
+
newEntry.matcher = matcher;
|
|
374
|
+
}
|
|
375
|
+
settings.hooks[event].push(newEntry);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
309
378
|
await writeJson(settingsPath, settings);
|
|
310
379
|
spinner.succeed(
|
|
311
380
|
chalk4.green(`Installed ${item.name} for ${AI_TOOLS[tool].name}`)
|
|
312
381
|
);
|
|
313
|
-
return { tool, success: true, path:
|
|
382
|
+
return { tool, success: true, path: destScriptPath };
|
|
314
383
|
} catch (error2) {
|
|
315
384
|
const errorMsg = error2 instanceof Error ? error2.message : "Unknown error";
|
|
316
385
|
spinner.fail(
|
|
@@ -493,14 +562,14 @@ var settingsHandler = {
|
|
|
493
562
|
|
|
494
563
|
// src/handlers/plugin.ts
|
|
495
564
|
import { homedir } from "os";
|
|
496
|
-
import { join as
|
|
565
|
+
import { join as join3 } from "path";
|
|
497
566
|
import chalk7 from "chalk";
|
|
498
567
|
import ora5 from "ora";
|
|
499
568
|
var home = homedir();
|
|
500
|
-
var PLUGINS_CACHE_DIR =
|
|
501
|
-
var INSTALLED_PLUGINS_PATH =
|
|
569
|
+
var PLUGINS_CACHE_DIR = join3(home, ".claude/plugins/cache");
|
|
570
|
+
var INSTALLED_PLUGINS_PATH = join3(home, ".claude/plugins/installed_plugins.json");
|
|
502
571
|
function getPluginCachePath(marketplace, name, version) {
|
|
503
|
-
return
|
|
572
|
+
return join3(PLUGINS_CACHE_DIR, marketplace, name, version);
|
|
504
573
|
}
|
|
505
574
|
function getPluginId(name, marketplace) {
|
|
506
575
|
return `${name}@${marketplace}`;
|
|
@@ -513,24 +582,39 @@ async function installPluginForTool(item, tool, scope, method, cwd) {
|
|
|
513
582
|
if (tool !== "claude") {
|
|
514
583
|
throw new Error("Plugins are only supported for Claude Code");
|
|
515
584
|
}
|
|
516
|
-
const
|
|
517
|
-
const version = "1.0.0";
|
|
518
|
-
const pluginId = getPluginId(item.slug, marketplace);
|
|
519
|
-
const cachePath = getPluginCachePath(marketplace, item.slug, version);
|
|
585
|
+
const tmpPath = join3(PLUGINS_CACHE_DIR, ".tmp", item.slug);
|
|
520
586
|
const sourcePath = getItemSourcePath(item);
|
|
521
587
|
if (sourcePath) {
|
|
522
|
-
await installDirectory(sourcePath,
|
|
588
|
+
await installDirectory(sourcePath, tmpPath, method);
|
|
523
589
|
} else {
|
|
524
|
-
await fetchItemToDestination(item,
|
|
590
|
+
await fetchItemToDestination(item, tmpPath);
|
|
525
591
|
}
|
|
592
|
+
const pluginJson = await readJson(
|
|
593
|
+
join3(tmpPath, ".claude-plugin", "plugin.json")
|
|
594
|
+
);
|
|
595
|
+
const marketplaceJson = await readJson(
|
|
596
|
+
join3(tmpPath, ".claude-plugin", "marketplace.json")
|
|
597
|
+
);
|
|
598
|
+
const marketplace = marketplaceJson.name || item.author?.name || "seedr";
|
|
599
|
+
const pluginName = pluginJson.name || item.slug;
|
|
600
|
+
const version = pluginJson.version || "1.0.0";
|
|
601
|
+
const pluginId = getPluginId(pluginName, marketplace);
|
|
602
|
+
const cachePath = getPluginCachePath(marketplace, pluginName, version);
|
|
603
|
+
const { rm } = await import("fs/promises");
|
|
604
|
+
await installDirectory(tmpPath, cachePath, "copy");
|
|
605
|
+
await rm(tmpPath, { recursive: true, force: true });
|
|
606
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
526
607
|
const registry = await readJson(INSTALLED_PLUGINS_PATH);
|
|
608
|
+
registry.version = registry.version || 2;
|
|
527
609
|
registry.plugins = registry.plugins || {};
|
|
528
610
|
const installInfo = {
|
|
529
611
|
scope,
|
|
530
|
-
|
|
612
|
+
...scope === "project" ? { projectPath: cwd } : {},
|
|
531
613
|
installPath: cachePath,
|
|
532
614
|
version,
|
|
533
|
-
installedAt:
|
|
615
|
+
installedAt: now,
|
|
616
|
+
lastUpdated: now,
|
|
617
|
+
gitCommitSha: ""
|
|
534
618
|
};
|
|
535
619
|
const existingEntries = registry.plugins[pluginId] || [];
|
|
536
620
|
const filteredEntries = existingEntries.filter(
|
|
@@ -716,14 +800,14 @@ function printInstallSummary(results) {
|
|
|
716
800
|
process.exit(1);
|
|
717
801
|
}
|
|
718
802
|
}
|
|
719
|
-
var addCommand = new Command("add").description("Install a skill, agent, hook, or other configuration").argument("[name]", "Name of the item to install").option("-
|
|
803
|
+
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: skill, agent, hook, mcp, plugin, settings").option(
|
|
720
804
|
"-a, --agents <tools>",
|
|
721
805
|
"Comma-separated AI tools or 'all' (claude,copilot,gemini,codex,opencode)"
|
|
722
|
-
).option("--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 what would be installed without making changes").action(async (name, options) => {
|
|
806
|
+
).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 what would be installed without making changes").action(async (name, options) => {
|
|
723
807
|
try {
|
|
724
808
|
printLogo();
|
|
725
809
|
intro2("Seedr");
|
|
726
|
-
const itemName = name
|
|
810
|
+
const itemName = name;
|
|
727
811
|
const contentType = options.type;
|
|
728
812
|
const item = await resolveItem(itemName, contentType);
|
|
729
813
|
if (!item) process.exit(1);
|
|
@@ -979,7 +1063,7 @@ var removeCommand = new Command3("remove").alias("rm").description("Remove an in
|
|
|
979
1063
|
import { Command as Command4 } from "commander";
|
|
980
1064
|
import chalk11 from "chalk";
|
|
981
1065
|
import ora7 from "ora";
|
|
982
|
-
import { join as
|
|
1066
|
+
import { join as join4 } from "path";
|
|
983
1067
|
var initCommand = new Command4("init").description("Initialize AI tool configuration directories").option(
|
|
984
1068
|
"-a, --agents <tools>",
|
|
985
1069
|
"Comma-separated AI tools or 'all'",
|
|
@@ -1014,7 +1098,7 @@ var initCommand = new Command4("init").description("Initialize AI tool configura
|
|
|
1014
1098
|
continue;
|
|
1015
1099
|
}
|
|
1016
1100
|
await ensureDir(path);
|
|
1017
|
-
const readmePath =
|
|
1101
|
+
const readmePath = join4(path, "README.md");
|
|
1018
1102
|
await writeTextFile(
|
|
1019
1103
|
readmePath,
|
|
1020
1104
|
`# ${AI_TOOLS[tool].name} Configuration
|