@arvoretech/hub 0.6.0 → 0.6.2

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/index.js CHANGED
@@ -1,7 +1,12 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ checkAndAutoRegenerate,
4
+ generateCommand,
5
+ loadHubConfig
6
+ } from "./chunk-BLVKDXNY.js";
2
7
 
3
8
  // src/index.ts
4
- import { Command as Command19 } from "commander";
9
+ import { Command as Command18 } from "commander";
5
10
 
6
11
  // src/commands/init.ts
7
12
  import { Command } from "commander";
@@ -140,8 +145,7 @@ var addRepoCommand = new Command2("add-repo").description("Add a repository to t
140
145
  url,
141
146
  ...opts.tech && { tech: opts.tech }
142
147
  });
143
- const header = content.startsWith("# yaml-language-server") ? "" : SCHEMA_COMMENT2;
144
- await writeFile2(configPath, header + stringify2(config), "utf-8");
148
+ await writeFile2(configPath, SCHEMA_COMMENT2 + stringify2(config), "utf-8");
145
149
  const gitignorePath = join2(hubDir, ".gitignore");
146
150
  await appendFile(gitignorePath, `${repoName}
147
151
  `);
@@ -164,20 +168,10 @@ Added ${repoName} to hub`));
164
168
  import { Command as Command3 } from "commander";
165
169
  import { existsSync as existsSync2 } from "fs";
166
170
  import { writeFile as writeFile3 } from "fs/promises";
167
- import { join as join4 } from "path";
171
+ import { join as join3 } from "path";
168
172
  import { execSync } from "child_process";
169
173
  import chalk3 from "chalk";
170
174
 
171
- // src/core/hub-config.ts
172
- import { readFile as readFile2 } from "fs/promises";
173
- import { join as join3 } from "path";
174
- import { parse as parse2 } from "yaml";
175
- async function loadHubConfig(dir) {
176
- const configPath = join3(dir, "hub.yaml");
177
- const content = await readFile2(configPath, "utf-8");
178
- return parse2(content);
179
- }
180
-
181
175
  // src/core/docker-compose.ts
182
176
  import { stringify as stringify3 } from "yaml";
183
177
  function generateDockerCompose(services) {
@@ -276,7 +270,7 @@ var setupCommand = new Command3("setup").description("Clone repos, start service
276
270
  \u2501\u2501\u2501 Step ${step}/${totalSteps}: Cloning repositories \u2501\u2501\u2501
277
271
  `));
278
272
  for (const repo of config.repos) {
279
- const fullPath = join4(hubDir, repo.path);
273
+ const fullPath = join3(hubDir, repo.path);
280
274
  console.log(chalk3.yellow(`\u25B8 ${repo.name}`));
281
275
  if (existsSync2(fullPath)) {
282
276
  console.log(chalk3.green(" Already exists, skipping"));
@@ -295,7 +289,7 @@ var setupCommand = new Command3("setup").description("Clone repos, start service
295
289
  console.log(chalk3.blue(`
296
290
  \u2501\u2501\u2501 Step ${step}/${totalSteps}: Starting services \u2501\u2501\u2501
297
291
  `));
298
- const composePath = join4(hubDir, "docker-compose.yml");
292
+ const composePath = join3(hubDir, "docker-compose.yml");
299
293
  const composeContent = generateDockerCompose(config.services);
300
294
  await writeFile3(composePath, composeContent, "utf-8");
301
295
  console.log(chalk3.green(" Generated docker-compose.yml"));
@@ -323,7 +317,7 @@ var setupCommand = new Command3("setup").description("Clone repos, start service
323
317
  } else {
324
318
  if (config.tools && Object.keys(config.tools).length > 0) {
325
319
  const content = generateMiseToml(config.tools, config.mise_settings);
326
- await writeFile3(join4(hubDir, ".mise.toml"), content, "utf-8");
320
+ await writeFile3(join3(hubDir, ".mise.toml"), content, "utf-8");
327
321
  console.log(chalk3.green(` Generated .mise.toml (${Object.keys(config.tools).length} tools)`));
328
322
  try {
329
323
  run("mise trust && mise install", hubDir);
@@ -334,11 +328,11 @@ var setupCommand = new Command3("setup").description("Clone repos, start service
334
328
  }
335
329
  for (const repo of config.repos) {
336
330
  if (!repo.tools || Object.keys(repo.tools).length === 0) continue;
337
- const repoDir = join4(hubDir, repo.path);
331
+ const repoDir = join3(hubDir, repo.path);
338
332
  if (!existsSync2(repoDir)) continue;
339
333
  const merged = { ...config.tools || {}, ...repo.tools };
340
334
  const content = generateMiseToml(merged);
341
- await writeFile3(join4(repoDir, ".mise.toml"), content, "utf-8");
335
+ await writeFile3(join3(repoDir, ".mise.toml"), content, "utf-8");
342
336
  console.log(chalk3.yellow(`\u25B8 ${repo.name}`));
343
337
  try {
344
338
  run("mise trust 2>/dev/null; mise install", repoDir);
@@ -355,10 +349,10 @@ var setupCommand = new Command3("setup").description("Clone repos, start service
355
349
  `));
356
350
  for (const repo of config.repos) {
357
351
  if (!repo.env_file) continue;
358
- const envPath = join4(hubDir, repo.path, repo.env_file);
352
+ const envPath = join3(hubDir, repo.path, repo.env_file);
359
353
  const overrides = config.env?.overrides?.["local"]?.[repo.name];
360
354
  if (overrides) {
361
- const dir = join4(hubDir, repo.path);
355
+ const dir = join3(hubDir, repo.path);
362
356
  if (existsSync2(dir)) {
363
357
  const lines = Object.entries(overrides).map(([k, v]) => `${k}=${v}`);
364
358
  await writeFile3(envPath, lines.join("\n") + "\n", "utf-8");
@@ -374,7 +368,7 @@ var setupCommand = new Command3("setup").description("Clone repos, start service
374
368
  \u2501\u2501\u2501 Step ${step}/${totalSteps}: Installing dependencies \u2501\u2501\u2501
375
369
  `));
376
370
  for (const repo of config.repos) {
377
- const fullPath = join4(hubDir, repo.path);
371
+ const fullPath = join3(hubDir, repo.path);
378
372
  if (!existsSync2(fullPath)) continue;
379
373
  const installCmd = repo.commands?.install;
380
374
  if (!installCmd) {
@@ -395,1023 +389,20 @@ var setupCommand = new Command3("setup").description("Clone repos, start service
395
389
  `));
396
390
  }
397
391
  console.log(chalk3.blue("\n\u2501\u2501\u2501 Setup complete \u2501\u2501\u2501\n"));
392
+ await checkAndAutoRegenerate(hubDir);
398
393
  console.log("Next steps:");
399
- console.log(` npx @arvoretech/hub generate --editor cursor`);
400
- console.log(` Open the project in Cursor and start building`);
394
+ console.log(` npx @arvoretech/hub generate`);
395
+ console.log(` Open the project in your editor and start building`);
401
396
  console.log();
402
397
  });
403
398
 
404
- // src/commands/generate.ts
399
+ // src/commands/env.ts
405
400
  import { Command as Command4 } from "commander";
406
401
  import { existsSync as existsSync3 } from "fs";
407
- import { mkdir as mkdir2, writeFile as writeFile4, readdir, copyFile, readFile as readFile3, cp } from "fs/promises";
408
- import { join as join5, resolve } from "path";
409
- import chalk4 from "chalk";
410
- var HUB_MARKER_START = "# >>> hub-managed (do not edit this section)";
411
- var HUB_MARKER_END = "# <<< hub-managed";
412
- var HOOK_EVENT_MAP = {
413
- session_start: { cursor: "sessionStart", claude: "SessionStart", kiro: void 0 },
414
- session_end: { cursor: "sessionEnd", claude: "SessionEnd", kiro: void 0 },
415
- pre_tool_use: { cursor: "preToolUse", claude: "PreToolUse", kiro: "pre_tool_use" },
416
- post_tool_use: { cursor: "postToolUse", claude: "PostToolUse", kiro: "post_tool_use" },
417
- post_tool_use_failure: { cursor: void 0, claude: "PostToolUseFailure", kiro: void 0 },
418
- stop: { cursor: "stop", claude: "Stop", kiro: "agent_stop" },
419
- subagent_start: { cursor: "subagentStart", claude: "SubagentStart", kiro: void 0 },
420
- subagent_stop: { cursor: "subagentStop", claude: "SubagentStop", kiro: void 0 },
421
- pre_compact: { cursor: "preCompact", claude: "PreCompact", kiro: void 0 },
422
- before_submit_prompt: { cursor: "beforeSubmitPrompt", claude: "UserPromptSubmit", kiro: "prompt_submit" },
423
- before_shell_execution: { cursor: "beforeShellExecution", claude: void 0, kiro: void 0 },
424
- after_shell_execution: { cursor: "afterShellExecution", claude: void 0, kiro: void 0 },
425
- before_mcp_execution: { cursor: "beforeMCPExecution", claude: void 0, kiro: void 0 },
426
- after_mcp_execution: { cursor: "afterMCPExecution", claude: void 0, kiro: void 0 },
427
- after_file_edit: { cursor: "afterFileEdit", claude: void 0, kiro: "file_save" },
428
- before_read_file: { cursor: "beforeReadFile", claude: void 0, kiro: void 0 },
429
- before_tab_file_read: { cursor: "beforeTabFileRead", claude: void 0, kiro: void 0 },
430
- after_tab_file_edit: { cursor: "afterTabFileEdit", claude: void 0, kiro: void 0 },
431
- after_agent_response: { cursor: "afterAgentResponse", claude: void 0, kiro: void 0 },
432
- after_agent_thought: { cursor: "afterAgentThought", claude: void 0, kiro: void 0 },
433
- notification: { cursor: void 0, claude: "Notification", kiro: void 0 },
434
- permission_request: { cursor: void 0, claude: "PermissionRequest", kiro: void 0 },
435
- task_completed: { cursor: void 0, claude: "TaskCompleted", kiro: void 0 },
436
- teammate_idle: { cursor: void 0, claude: "TeammateIdle", kiro: void 0 }
437
- };
438
- function buildCursorHooks(hooks) {
439
- const cursorHooks = {};
440
- for (const [event, entries] of Object.entries(hooks)) {
441
- const mapped = HOOK_EVENT_MAP[event]?.cursor;
442
- if (!mapped) continue;
443
- const cursorEntries = entries.map((entry) => {
444
- const obj = { type: entry.type };
445
- if (entry.type === "command" && entry.command) obj.command = entry.command;
446
- if (entry.type === "prompt" && entry.prompt) obj.prompt = entry.prompt;
447
- if (entry.matcher) obj.matcher = entry.matcher;
448
- if (entry.timeout_ms) obj.timeout = entry.timeout_ms;
449
- return obj;
450
- });
451
- if (cursorEntries.length > 0) {
452
- cursorHooks[mapped] = cursorEntries;
453
- }
454
- }
455
- if (Object.keys(cursorHooks).length === 0) return null;
456
- return { version: 1, hooks: cursorHooks };
457
- }
458
- function buildClaudeHooks(hooks) {
459
- const claudeHooks = {};
460
- for (const [event, entries] of Object.entries(hooks)) {
461
- const mapped = HOOK_EVENT_MAP[event]?.claude;
462
- if (!mapped) continue;
463
- const claudeEntries = entries.map((entry) => {
464
- const obj = { type: entry.type };
465
- if (entry.type === "command" && entry.command) obj.command = entry.command;
466
- if (entry.type === "prompt" && entry.prompt) obj.prompt = entry.prompt;
467
- if (entry.matcher) obj.matcher = entry.matcher;
468
- if (entry.timeout_ms) obj.timeout = entry.timeout_ms;
469
- return obj;
470
- });
471
- if (claudeEntries.length > 0) {
472
- claudeHooks[mapped] = claudeEntries;
473
- }
474
- }
475
- if (Object.keys(claudeHooks).length === 0) return null;
476
- return claudeHooks;
477
- }
478
- async function generateCursorCommands(config, hubDir, cursorDir) {
479
- const commandsDir = join5(cursorDir, "commands");
480
- let count = 0;
481
- if (config.commands_dir) {
482
- const srcDir = resolve(hubDir, config.commands_dir);
483
- try {
484
- const files = await readdir(srcDir);
485
- const mdFiles = files.filter((f) => f.endsWith(".md"));
486
- if (mdFiles.length > 0) {
487
- await mkdir2(commandsDir, { recursive: true });
488
- for (const file of mdFiles) {
489
- await copyFile(join5(srcDir, file), join5(commandsDir, file));
490
- count++;
491
- }
492
- }
493
- } catch {
494
- console.log(chalk4.yellow(` Commands directory ${config.commands_dir} not found, skipping`));
495
- }
496
- }
497
- if (config.commands) {
498
- await mkdir2(commandsDir, { recursive: true });
499
- for (const [name, filePath] of Object.entries(config.commands)) {
500
- const src = resolve(hubDir, filePath);
501
- const dest = join5(commandsDir, name.endsWith(".md") ? name : `${name}.md`);
502
- try {
503
- await copyFile(src, dest);
504
- count++;
505
- } catch {
506
- console.log(chalk4.yellow(` Command file ${filePath} not found, skipping`));
507
- }
508
- }
509
- }
510
- if (count > 0) {
511
- console.log(chalk4.green(` Copied ${count} commands to .cursor/commands/`));
512
- }
513
- }
514
- async function writeManagedFile(filePath, managedLines) {
515
- const managedBlock = [HUB_MARKER_START, ...managedLines, HUB_MARKER_END].join("\n");
516
- if (existsSync3(filePath)) {
517
- const existing = await readFile3(filePath, "utf-8");
518
- const startIdx = existing.indexOf(HUB_MARKER_START);
519
- const endIdx = existing.indexOf(HUB_MARKER_END);
520
- if (startIdx !== -1 && endIdx !== -1) {
521
- const before = existing.substring(0, startIdx);
522
- const after = existing.substring(endIdx + HUB_MARKER_END.length);
523
- await writeFile4(filePath, before + managedBlock + after, "utf-8");
524
- return;
525
- }
526
- await writeFile4(filePath, managedBlock + "\n\n" + existing, "utf-8");
527
- return;
528
- }
529
- await writeFile4(filePath, managedBlock + "\n", "utf-8");
530
- }
531
- async function generateCursor(config, hubDir) {
532
- const cursorDir = join5(hubDir, ".cursor");
533
- await mkdir2(join5(cursorDir, "rules"), { recursive: true });
534
- await mkdir2(join5(cursorDir, "agents"), { recursive: true });
535
- const gitignoreLines = buildGitignoreLines(config);
536
- await writeManagedFile(join5(hubDir, ".gitignore"), gitignoreLines);
537
- console.log(chalk4.green(" Generated .gitignore"));
538
- const cursorignoreLines = [
539
- "# Re-include repositories for AI context"
540
- ];
541
- for (const repo of config.repos) {
542
- const repoDir = repo.path.replace("./", "");
543
- cursorignoreLines.push(`!${repoDir}/`);
544
- }
545
- cursorignoreLines.push("", "# Re-include tasks for agent collaboration", "!tasks/");
546
- await writeManagedFile(join5(hubDir, ".cursorignore"), cursorignoreLines);
547
- console.log(chalk4.green(" Generated .cursorignore"));
548
- if (config.mcps?.length) {
549
- const mcpConfig = {};
550
- for (const mcp of config.mcps) {
551
- mcpConfig[mcp.name] = buildCursorMcpEntry(mcp);
552
- }
553
- await writeFile4(
554
- join5(cursorDir, "mcp.json"),
555
- JSON.stringify({ mcpServers: mcpConfig }, null, 2) + "\n",
556
- "utf-8"
557
- );
558
- console.log(chalk4.green(" Generated .cursor/mcp.json"));
559
- }
560
- const orchestratorRule = buildOrchestratorRule(config);
561
- await writeFile4(join5(cursorDir, "rules", "orchestrator.mdc"), orchestratorRule, "utf-8");
562
- console.log(chalk4.green(" Generated .cursor/rules/orchestrator.mdc"));
563
- const agentsDir = resolve(hubDir, "agents");
564
- try {
565
- const agentFiles = await readdir(agentsDir);
566
- const mdFiles = agentFiles.filter((f) => f.endsWith(".md"));
567
- for (const file of mdFiles) {
568
- await copyFile(join5(agentsDir, file), join5(cursorDir, "agents", file));
569
- }
570
- console.log(chalk4.green(` Copied ${mdFiles.length} agent definitions`));
571
- } catch {
572
- console.log(chalk4.yellow(" No agents/ directory found, skipping agent copy"));
573
- }
574
- const skillsDir = resolve(hubDir, "skills");
575
- try {
576
- const skillFolders = await readdir(skillsDir);
577
- const cursorSkillsDir = join5(cursorDir, "skills");
578
- await mkdir2(cursorSkillsDir, { recursive: true });
579
- let count = 0;
580
- for (const folder of skillFolders) {
581
- const skillFile = join5(skillsDir, folder, "SKILL.md");
582
- try {
583
- await readFile3(skillFile);
584
- const srcDir = join5(skillsDir, folder);
585
- const targetDir = join5(cursorSkillsDir, folder);
586
- await cp(srcDir, targetDir, { recursive: true });
587
- count++;
588
- } catch {
589
- }
590
- }
591
- if (count > 0) {
592
- console.log(chalk4.green(` Copied ${count} skills`));
593
- }
594
- } catch {
595
- }
596
- if (config.hooks) {
597
- const cursorHooks = buildCursorHooks(config.hooks);
598
- if (cursorHooks) {
599
- await writeFile4(
600
- join5(cursorDir, "hooks.json"),
601
- JSON.stringify(cursorHooks, null, 2) + "\n",
602
- "utf-8"
603
- );
604
- console.log(chalk4.green(" Generated .cursor/hooks.json"));
605
- }
606
- }
607
- await generateCursorCommands(config, hubDir, cursorDir);
608
- await generateVSCodeSettings(config, hubDir);
609
- }
610
- function buildCursorMcpEntry(mcp) {
611
- if (mcp.url) {
612
- return { url: mcp.url, ...mcp.env && { env: mcp.env } };
613
- }
614
- if (mcp.image) {
615
- const args = ["run", "-i", "--rm"];
616
- if (mcp.env) {
617
- for (const [key, value] of Object.entries(mcp.env)) {
618
- args.push("-e", `${key}=${value}`);
619
- }
620
- }
621
- args.push(mcp.image);
622
- return { command: "docker", args };
623
- }
624
- return {
625
- command: "npx",
626
- args: ["-y", mcp.package],
627
- ...mcp.env && { env: mcp.env }
628
- };
629
- }
630
- function buildClaudeCodeMcpEntry(mcp) {
631
- if (mcp.url) {
632
- return { type: "http", url: mcp.url };
633
- }
634
- if (mcp.image) {
635
- const args = ["run", "-i", "--rm"];
636
- if (mcp.env) {
637
- for (const [key, value] of Object.entries(mcp.env)) {
638
- args.push("-e", `${key}=${value}`);
639
- }
640
- }
641
- args.push(mcp.image);
642
- return { command: "docker", args };
643
- }
644
- return {
645
- command: "npx",
646
- args: ["-y", mcp.package],
647
- ...mcp.env && { env: mcp.env }
648
- };
649
- }
650
- function buildKiroMcpEntry(mcp) {
651
- if (mcp.url) {
652
- return { url: mcp.url, ...mcp.env && { env: mcp.env } };
653
- }
654
- if (mcp.image) {
655
- const args = ["run", "-i", "--rm"];
656
- if (mcp.env) {
657
- for (const [key, value] of Object.entries(mcp.env)) {
658
- args.push("-e", `${key}=${value}`);
659
- }
660
- }
661
- args.push(mcp.image);
662
- return { command: "docker", args };
663
- }
664
- return {
665
- command: "npx",
666
- args: ["-y", mcp.package],
667
- ...mcp.env && { env: mcp.env }
668
- };
669
- }
670
- function buildKiroSteeringContent(content, inclusion = "always", meta) {
671
- const frontMatter = ["---", `inclusion: ${inclusion}`];
672
- if (meta?.name) frontMatter.push(`name: ${meta.name}`);
673
- if (meta?.description) frontMatter.push(`description: ${meta.description}`);
674
- frontMatter.push("---");
675
- return `${frontMatter.join("\n")}
676
-
677
- ${content}`;
678
- }
679
- function buildKiroOrchestratorRule(config) {
680
- const taskFolder = config.workflow?.task_folder || "./tasks/<TASK_ID>/";
681
- const steps = config.workflow?.pipeline || [];
682
- const prompt = config.workflow?.prompt;
683
- const enforce = config.workflow?.enforce_workflow ?? false;
684
- const sections = [];
685
- sections.push(`# Orchestrator
686
-
687
- ## Your Main Responsibility
688
-
689
- You are the development orchestrator. Your job is to ensure that any feature or task requested by the user is completed end-to-end by following a structured pipeline. You work as a single agent but follow specialized instructions from steering files for each phase of development.
690
-
691
- > **Note:** This workspace uses steering files in \`.kiro/steering/\` to provide role-specific instructions for each pipeline step. When a step says "follow the instructions from steering file X", read that file and apply its guidelines to the current task.`);
692
- if (enforce) {
693
- sections.push(`
694
- ## STRICT WORKFLOW ENFORCEMENT
695
-
696
- **YOU MUST FOLLOW THE PIPELINE DEFINED BELOW. NO EXCEPTIONS.**
697
-
698
- - NEVER skip a pipeline step, even if the task seems simple or obvious.
699
- - ALWAYS execute steps in the exact order defined. Do not reorder, merge, or parallelize steps unless the pipeline explicitly allows it.
700
- - ALWAYS follow the designated steering file for each step. Do not improvise if a steering file is assigned.
701
- - ALWAYS wait for a step to complete and validate its output before moving to the next step.
702
- - If a step produces a document, READ the document and confirm it is complete before proceeding.
703
- - If a step has unanswered questions or validation issues, RESOLVE them before advancing.
704
- - NEVER jump directly to coding without completing refinement first.
705
- - NEVER skip review or QA steps, even for small changes.
706
- - If the user asks you to skip a step, explain why the pipeline exists and ask for explicit confirmation before proceeding.`);
707
- }
708
- if (prompt?.prepend) {
709
- sections.push(`
710
- ${prompt.prepend.trim()}`);
711
- }
712
- if (config.integrations?.linear) {
713
- const linear = config.integrations.linear;
714
- sections.push(`
715
- ## Task Management
716
-
717
- If the user doesn't have a task in their project management tool, create one using the Linear MCP.${linear.team ? ` Add it to the **${linear.team}** team.` : ""} Provide the link to the user so they can review and modify as needed.`);
718
- }
719
- sections.push(`
720
- ## Repositories
721
- `);
722
- for (const repo of config.repos) {
723
- const parts = [`- **${repo.path}**`];
724
- if (repo.description) parts.push(`\u2014 ${repo.description}`);
725
- else if (repo.tech) parts.push(`\u2014 ${repo.tech}`);
726
- if (repo.skills?.length) parts.push(`(skills: ${repo.skills.join(", ")})`);
727
- sections.push(parts.join(" "));
728
- if (repo.commands) {
729
- const cmds = Object.entries(repo.commands).filter(([, v]) => v).map(([k, v]) => `\`${k}\`: \`${v}\``).join(", ");
730
- if (cmds) sections.push(` Commands: ${cmds}`);
731
- }
732
- }
733
- if (prompt?.sections?.after_repositories) {
734
- sections.push(`
735
- ${prompt.sections.after_repositories.trim()}`);
736
- }
737
- const docStructure = buildDocumentStructure(steps, taskFolder);
738
- sections.push(docStructure);
739
- const pipelineSection = buildKiroPipelineSection(steps);
740
- sections.push(pipelineSection);
741
- if (prompt?.sections?.after_pipeline) {
742
- sections.push(`
743
- ${prompt.sections.after_pipeline.trim()}`);
744
- }
745
- if (config.integrations?.slack || config.integrations?.github) {
746
- sections.push(buildDeliverySection(config));
747
- }
748
- if (prompt?.sections?.after_delivery) {
749
- sections.push(`
750
- ${prompt.sections.after_delivery.trim()}`);
751
- }
752
- if (config.memory) {
753
- sections.push(`
754
- ## Team Memory
755
-
756
- This workspace has a team memory knowledge base available via the \`team-memory\` MCP.
757
-
758
- **Before starting any task**, use \`search_memories\` to find relevant context \u2014 past decisions, conventions, known issues, and domain knowledge. This avoids repeating mistakes and ensures consistency with previous choices.
759
-
760
- **After completing a task**, if you discovered something valuable (a decision, a gotcha, a convention, domain insight), use \`add_memory\` to capture it for the team.
761
-
762
- Available tools: \`search_memories\`, \`get_memory\`, \`add_memory\`, \`list_memories\`, \`archive_memory\`, \`remove_memory\`.`);
763
- }
764
- sections.push(`
765
- ## Troubleshooting and Debugging
766
-
767
- For bug reports or unexpected behavior, follow the debugging process from the \`agent-debugger.md\` steering file (if available), or:
768
- 1. Collect context (symptoms, environment, timeline)
769
- 2. Analyze logs and stack traces
770
- 3. Form and test hypotheses systematically
771
- 4. Identify the root cause
772
- 5. Propose and implement the fix`);
773
- if (prompt?.sections) {
774
- const reservedKeys = /* @__PURE__ */ new Set(["after_repositories", "after_pipeline", "after_delivery"]);
775
- for (const [name, content] of Object.entries(prompt.sections)) {
776
- if (reservedKeys.has(name)) continue;
777
- const title = name.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
778
- sections.push(`
779
- ## ${title}
780
-
781
- ${content.trim()}`);
782
- }
783
- }
784
- if (prompt?.append) {
785
- sections.push(`
786
- ${prompt.append.trim()}`);
787
- }
788
- return sections.join("\n");
789
- }
790
- function buildKiroPipelineSection(steps) {
791
- if (steps.length === 0) {
792
- return `
793
- ## Development Pipeline
794
-
795
- Since Kiro does not support sub-agents, follow each step sequentially, applying the guidelines from the corresponding steering file:
796
-
797
- 1. **Refinement** \u2014 Read and follow \`agent-refinement.md\` steering file to collect requirements. Write output to the task document.
798
- 2. **Coding** \u2014 Follow the coding steering files (\`agent-coding-backend.md\`, \`agent-coding-frontend.md\`) to implement the feature.
799
- 3. **Review** \u2014 Follow \`agent-code-reviewer.md\` to review the implementation.
800
- 4. **QA** \u2014 Follow \`agent-qa-backend.md\` and/or \`agent-qa-frontend.md\` to test.
801
- 5. **Delivery** \u2014 Create PRs and notify the team.`;
802
- }
803
- const parts = [`
804
- ## Development Pipeline
805
-
806
- Follow each step sequentially, applying the role-specific instructions from the corresponding steering file at each phase.
807
- `];
808
- for (const step of steps) {
809
- if (step.actions) {
810
- parts.push(`### Delivery`);
811
- parts.push(`After all validations pass, execute these actions:`);
812
- for (const action of step.actions) {
813
- parts.push(`- ${formatAction(action)}`);
814
- }
815
- continue;
816
- }
817
- const stepTitle = step.step.charAt(0).toUpperCase() + step.step.slice(1);
818
- parts.push(`### ${stepTitle}`);
819
- if (step.mode === "plan") {
820
- parts.push(`**This step is a planning phase.** Do NOT make any code changes. Focus on reading, analyzing, and collaborating with the user to define requirements before proceeding.`);
821
- parts.push(``);
822
- }
823
- if (step.agent) {
824
- parts.push(`Follow the instructions from the \`agent-${step.agent}.md\` steering file.${step.output ? ` Write output to \`${step.output}\`.` : ""}`);
825
- if (step.step === "refinement") {
826
- parts.push(`
827
- After completing the refinement, validate with the user:
828
- - If there are unanswered questions, ask the user one at a time
829
- - If the user requests adjustments, revisit the refinement
830
- - Do not proceed until the document is complete and approved by the user`);
831
- }
832
- }
833
- if (Array.isArray(step.agents)) {
834
- const agentList = step.agents.map((a) => {
835
- if (typeof a === "string") return { agent: a };
836
- return a;
837
- });
838
- parts.push(`Follow the instructions from these steering files sequentially:`);
839
- for (const a of agentList) {
840
- let line = `- \`agent-${a.agent}.md\``;
841
- if (a.output) line += ` \u2192 write to \`${a.output}\``;
842
- if (a.when) line += ` (when: ${a.when})`;
843
- parts.push(line);
844
- }
845
- if (step.step === "coding" || step.step === "code" || step.step === "implementation") {
846
- parts.push(`
847
- If you encounter doubts during coding, write questions in the task document and validate with the user before proceeding.`);
848
- }
849
- if (step.step === "validation" || step.step === "review" || step.step === "qa") {
850
- parts.push(`
851
- If any validation step reveals issues requiring fixes, go back to the relevant coding step to address them.`);
852
- }
853
- }
854
- parts.push("");
855
- }
856
- return parts.join("\n");
857
- }
858
- function buildOrchestratorRule(config) {
859
- const taskFolder = config.workflow?.task_folder || "./tasks/<TASK_ID>/";
860
- const steps = config.workflow?.pipeline || [];
861
- const prompt = config.workflow?.prompt;
862
- const enforce = config.workflow?.enforce_workflow ?? false;
863
- const sections = [];
864
- sections.push(`---
865
- description: "Orchestrator agent \u2014 coordinates sub-agents through the development pipeline"
866
- alwaysApply: true
867
- ---
868
-
869
- # Orchestrator
870
-
871
- ## Your Main Responsibility
872
-
873
- You are an agent orchestrator. Your job is to ensure that any feature or task requested by the user is completed end-to-end using specialized sub-agents.`);
874
- if (enforce) {
875
- sections.push(`
876
- ## STRICT WORKFLOW ENFORCEMENT
877
-
878
- **YOU MUST FOLLOW THE PIPELINE DEFINED BELOW. NO EXCEPTIONS.**
879
-
880
- - NEVER skip a pipeline step, even if the task seems simple or obvious.
881
- - ALWAYS execute steps in the exact order defined. Do not reorder, merge, or parallelize steps unless the pipeline explicitly allows it.
882
- - ALWAYS call the designated sub-agent for each step. Do not attempt to perform a step yourself if an agent is assigned to it.
883
- - ALWAYS wait for a step to complete and validate its output before moving to the next step.
884
- - If a step produces a document, READ the document and confirm it is complete before proceeding.
885
- - If a step has unanswered questions or validation issues, RESOLVE them before advancing.
886
- - NEVER jump directly to coding without completing refinement first.
887
- - NEVER skip review or QA steps, even for small changes.
888
- - If the user asks you to skip a step, explain why the pipeline exists and ask for explicit confirmation before proceeding.`);
889
- }
890
- if (prompt?.prepend) {
891
- sections.push(`
892
- ${prompt.prepend.trim()}`);
893
- }
894
- if (config.integrations?.linear) {
895
- const linear = config.integrations.linear;
896
- sections.push(`
897
- ## Task Management
898
-
899
- If the user doesn't have a task in their project management tool, create one using the Linear MCP.${linear.team ? ` Add it to the **${linear.team}** team.` : ""} Provide the link to the user so they can review and modify as needed.`);
900
- }
901
- sections.push(`
902
- ## Repositories
903
- `);
904
- for (const repo of config.repos) {
905
- const parts = [`- **${repo.path}**`];
906
- if (repo.description) parts.push(`\u2014 ${repo.description}`);
907
- else if (repo.tech) parts.push(`\u2014 ${repo.tech}`);
908
- if (repo.skills?.length) parts.push(`(skills: ${repo.skills.join(", ")})`);
909
- sections.push(parts.join(" "));
910
- if (repo.commands) {
911
- const cmds = Object.entries(repo.commands).filter(([, v]) => v).map(([k, v]) => `\`${k}\`: \`${v}\``).join(", ");
912
- if (cmds) sections.push(` Commands: ${cmds}`);
913
- }
914
- }
915
- if (prompt?.sections?.after_repositories) {
916
- sections.push(`
917
- ${prompt.sections.after_repositories.trim()}`);
918
- }
919
- const docStructure = buildDocumentStructure(steps, taskFolder);
920
- sections.push(docStructure);
921
- const pipelineSection = buildPipelineSection(steps);
922
- sections.push(pipelineSection);
923
- if (prompt?.sections?.after_pipeline) {
924
- sections.push(`
925
- ${prompt.sections.after_pipeline.trim()}`);
926
- }
927
- if (config.integrations?.slack || config.integrations?.github) {
928
- sections.push(buildDeliverySection(config));
929
- }
930
- if (prompt?.sections?.after_delivery) {
931
- sections.push(`
932
- ${prompt.sections.after_delivery.trim()}`);
933
- }
934
- if (config.memory) {
935
- sections.push(`
936
- ## Team Memory
937
-
938
- This workspace has a team memory knowledge base available via the \`team-memory\` MCP.
939
-
940
- **Before starting any task**, use \`search_memories\` to find relevant context \u2014 past decisions, conventions, known issues, and domain knowledge. This avoids repeating mistakes and ensures consistency with previous choices.
941
-
942
- **After completing a task**, if you discovered something valuable (a decision, a gotcha, a convention, domain insight), use \`add_memory\` to capture it for the team.
943
-
944
- Available tools: \`search_memories\`, \`get_memory\`, \`add_memory\`, \`list_memories\`, \`archive_memory\`, \`remove_memory\`.`);
945
- }
946
- sections.push(`
947
- ## Troubleshooting and Debugging
948
-
949
- For bug reports or unexpected behavior, use the \`debugger\` agent directly.
950
- It will:
951
- 1. Collect context (symptoms, environment, timeline)
952
- 2. Analyze logs and stack traces
953
- 3. Form and test hypotheses systematically
954
- 4. Identify the root cause
955
- 5. Propose a solution or call coding agents to implement the fix`);
956
- if (prompt?.sections) {
957
- const reservedKeys = /* @__PURE__ */ new Set(["after_repositories", "after_pipeline", "after_delivery"]);
958
- for (const [name, content] of Object.entries(prompt.sections)) {
959
- if (reservedKeys.has(name)) continue;
960
- const title = name.split(/[-_]/).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
961
- sections.push(`
962
- ## ${title}
963
-
964
- ${content.trim()}`);
965
- }
966
- }
967
- if (prompt?.append) {
968
- sections.push(`
969
- ${prompt.append.trim()}`);
970
- }
971
- return sections.join("\n");
972
- }
973
- function buildDocumentStructure(steps, taskFolder) {
974
- const outputs = [];
975
- for (const step of steps) {
976
- if (step.output) {
977
- outputs.push(step.output);
978
- }
979
- if (Array.isArray(step.agents)) {
980
- for (const a of step.agents) {
981
- if (typeof a === "object" && a.output) {
982
- outputs.push(a.output);
983
- }
984
- }
985
- }
986
- }
987
- if (outputs.length === 0) {
988
- outputs.push("refinement.md", "code-backend.md", "code-frontend.md", "code-review.md", "qa-backend.md", "qa-frontend.md");
989
- }
990
- const tree = outputs.map((o) => `\u251C\u2500\u2500 ${o}`);
991
- if (tree.length > 0) {
992
- tree[tree.length - 1] = tree[tree.length - 1].replace("\u251C\u2500\u2500", "\u2514\u2500\u2500");
993
- }
994
- return `
995
- ## Document Structure
996
-
997
- All task documents are stored in \`${taskFolder}\`:
998
-
999
- \`\`\`
1000
- ${taskFolder}
1001
- ${tree.join("\n")}
1002
- \`\`\``;
1003
- }
1004
- function buildPipelineSection(steps) {
1005
- if (steps.length === 0) {
1006
- return `
1007
- ## Development Pipeline
1008
-
1009
- 1. Use the \`refinement\` agent to collect requirements
1010
- 2. Use \`coding-backend\` and/or \`coding-frontend\` agents to implement
1011
- 3. Use \`code-reviewer\` to review the implementation
1012
- 4. Use \`qa-backend\` and/or \`qa-frontend\` to test
1013
- 5. Create PRs and notify the team`;
1014
- }
1015
- const parts = [`
1016
- ## Development Pipeline
1017
- `];
1018
- for (const step of steps) {
1019
- if (step.actions) {
1020
- parts.push(`### Delivery`);
1021
- parts.push(`After all validations pass, execute these actions:`);
1022
- for (const action of step.actions) {
1023
- parts.push(`- ${formatAction(action)}`);
1024
- }
1025
- continue;
1026
- }
1027
- const stepTitle = step.step.charAt(0).toUpperCase() + step.step.slice(1);
1028
- parts.push(`### ${stepTitle}`);
1029
- if (step.mode === "plan") {
1030
- parts.push(`**Before starting this step, switch to Plan Mode** by calling \`SwitchMode\` with \`target_mode_id: "plan"\`. This ensures collaborative planning with the user in a read-only context before any implementation begins.`);
1031
- parts.push(``);
1032
- }
1033
- if (step.agent) {
1034
- parts.push(`Call the \`${step.agent}\` agent.${step.output ? ` It writes to \`${step.output}\`.` : ""}`);
1035
- if (step.step === "refinement") {
1036
- parts.push(`
1037
- After it runs, read the document and validate with the user:
1038
- - If there are unanswered questions, ask the user one at a time
1039
- - If the user requests adjustments, send back to the refinement agent
1040
- - Do not proceed until the document is complete and approved by the user`);
1041
- }
1042
- }
1043
- if (Array.isArray(step.agents)) {
1044
- const agentList = step.agents.map((a) => {
1045
- if (typeof a === "string") return { agent: a };
1046
- return a;
1047
- });
1048
- if (step.parallel) {
1049
- parts.push(`Call these agents${step.parallel ? " in parallel" : ""}:`);
1050
- } else {
1051
- parts.push(`Call these agents in sequence:`);
1052
- }
1053
- for (const a of agentList) {
1054
- let line = `- \`${a.agent}\``;
1055
- if (a.output) line += ` \u2192 writes to \`${a.output}\``;
1056
- if (a.when) line += ` (when: ${a.when})`;
1057
- parts.push(line);
1058
- }
1059
- if (step.step === "coding" || step.step === "code" || step.step === "implementation") {
1060
- parts.push(`
1061
- If any coding agent has doubts, they will write questions in their document. Apply the same Q&A logic as refinement \u2014 validate with the user before proceeding.`);
1062
- }
1063
- if (step.step === "validation" || step.step === "review" || step.step === "qa") {
1064
- parts.push(`
1065
- If any validation agent leaves comments requiring fixes, call the relevant coding agents again to address them.`);
1066
- }
1067
- }
1068
- if (step.mode === "plan") {
1069
- parts.push(`
1070
- **After this step is complete and approved**, switch back to Agent Mode to proceed with the next step.`);
1071
- }
1072
- parts.push("");
1073
- }
1074
- return parts.join("\n");
1075
- }
1076
- function buildDeliverySection(config) {
1077
- const parts = [`
1078
- ## Delivery Details
1079
- `];
1080
- if (config.integrations?.github) {
1081
- const gh = config.integrations.github;
1082
- parts.push(`### Pull Requests`);
1083
- parts.push(`For each repository with changes, push the branch and create a PR using the GitHub MCP.`);
1084
- if (gh.pr_branch_pattern) {
1085
- parts.push(`Branch naming pattern: \`${gh.pr_branch_pattern}\``);
1086
- }
1087
- }
1088
- if (config.integrations?.slack) {
1089
- const slack = config.integrations.slack;
1090
- if (slack.channels) {
1091
- parts.push(`
1092
- ### Slack Notifications`);
1093
- for (const [purpose, channel] of Object.entries(slack.channels)) {
1094
- parts.push(`- **${purpose}**: Post to \`${channel}\``);
1095
- }
1096
- }
1097
- if (slack.templates) {
1098
- parts.push(`
1099
- Message templates:`);
1100
- for (const [name, template] of Object.entries(slack.templates)) {
1101
- parts.push(`- **${name}**: \`${template}\``);
1102
- }
1103
- }
1104
- }
1105
- if (config.integrations?.linear) {
1106
- parts.push(`
1107
- ### Task Management`);
1108
- parts.push(`Update the Linear task status after PR creation.`);
1109
- }
1110
- return parts.join("\n");
1111
- }
1112
- function formatAction(action) {
1113
- const map = {
1114
- "create-pr": "Create pull requests for each repository with changes",
1115
- "notify-slack": "Send notification to the configured Slack channel",
1116
- "notify-slack-prs": "Send PR notification to the Slack PRs channel",
1117
- "update-linear": "Update the Linear task status",
1118
- "update-linear-status": "Update the Linear task status to Review",
1119
- "update-jira": "Update the Jira task status"
1120
- };
1121
- return map[action] || action;
1122
- }
1123
- async function generateClaudeCode(config, hubDir) {
1124
- const claudeDir = join5(hubDir, ".claude");
1125
- await mkdir2(join5(claudeDir, "agents"), { recursive: true });
1126
- const orchestratorRule = buildOrchestratorRule(config);
1127
- const cleanedOrchestrator = orchestratorRule.replace(/^---[\s\S]*?---\n/m, "").trim();
1128
- const claudeMdSections = [];
1129
- claudeMdSections.push(cleanedOrchestrator);
1130
- const agentsDir = resolve(hubDir, "agents");
1131
- try {
1132
- const agentFiles = await readdir(agentsDir);
1133
- const mdFiles = agentFiles.filter((f) => f.endsWith(".md"));
1134
- for (const file of mdFiles) {
1135
- await copyFile(join5(agentsDir, file), join5(claudeDir, "agents", file));
1136
- }
1137
- console.log(chalk4.green(` Copied ${mdFiles.length} agents to .claude/agents/`));
1138
- } catch {
1139
- console.log(chalk4.yellow(" No agents/ directory found, skipping agent copy"));
1140
- }
1141
- const skillsDir = resolve(hubDir, "skills");
1142
- try {
1143
- const skillFolders = await readdir(skillsDir);
1144
- const claudeSkillsDir = join5(claudeDir, "skills");
1145
- await mkdir2(claudeSkillsDir, { recursive: true });
1146
- let count = 0;
1147
- for (const folder of skillFolders) {
1148
- const skillFile = join5(skillsDir, folder, "SKILL.md");
1149
- try {
1150
- await readFile3(skillFile);
1151
- const srcDir = join5(skillsDir, folder);
1152
- const targetDir = join5(claudeSkillsDir, folder);
1153
- await cp(srcDir, targetDir, { recursive: true });
1154
- count++;
1155
- } catch {
1156
- }
1157
- }
1158
- if (count > 0) {
1159
- console.log(chalk4.green(` Copied ${count} skills to .claude/skills/`));
1160
- }
1161
- } catch {
1162
- }
1163
- await writeFile4(join5(hubDir, "CLAUDE.md"), claudeMdSections.join("\n"), "utf-8");
1164
- console.log(chalk4.green(" Generated CLAUDE.md"));
1165
- if (config.mcps?.length) {
1166
- const mcpJson = {};
1167
- for (const mcp of config.mcps) {
1168
- mcpJson[mcp.name] = buildClaudeCodeMcpEntry(mcp);
1169
- }
1170
- await writeFile4(
1171
- join5(hubDir, ".mcp.json"),
1172
- JSON.stringify({ mcpServers: mcpJson }, null, 2) + "\n",
1173
- "utf-8"
1174
- );
1175
- console.log(chalk4.green(" Generated .mcp.json"));
1176
- }
1177
- const mcpServerNames = config.mcps?.map((m) => m.name) || [];
1178
- const claudeSettings = {
1179
- $schema: "https://json.schemastore.org/claude-code-settings.json",
1180
- permissions: {
1181
- allow: [
1182
- "Read(*)",
1183
- "Edit(*)",
1184
- "Write(*)",
1185
- "Bash(git *)",
1186
- "Bash(npm *)",
1187
- "Bash(pnpm *)",
1188
- "Bash(npx *)",
1189
- "Bash(ls *)",
1190
- "Bash(echo *)",
1191
- "Bash(grep *)",
1192
- ...mcpServerNames.map((name) => `mcp__${name}__*`)
1193
- ],
1194
- deny: [
1195
- "Read(.env)",
1196
- "Read(.env.*)",
1197
- "Read(**/.env)",
1198
- "Read(**/.env.*)",
1199
- "Read(**/credentials*)",
1200
- "Read(**/secrets*)",
1201
- "Read(**/*.pem)",
1202
- "Read(**/*.key)"
1203
- ]
1204
- },
1205
- enableAllProjectMcpServers: true
1206
- };
1207
- if (config.hooks) {
1208
- const claudeHooks = buildClaudeHooks(config.hooks);
1209
- if (claudeHooks) {
1210
- claudeSettings.hooks = claudeHooks;
1211
- }
1212
- }
1213
- await writeFile4(
1214
- join5(claudeDir, "settings.json"),
1215
- JSON.stringify(claudeSettings, null, 2) + "\n",
1216
- "utf-8"
1217
- );
1218
- console.log(chalk4.green(" Generated .claude/settings.json"));
1219
- const gitignoreLines = buildGitignoreLines(config);
1220
- await writeManagedFile(join5(hubDir, ".gitignore"), gitignoreLines);
1221
- console.log(chalk4.green(" Generated .gitignore"));
1222
- }
1223
- async function generateKiro(config, hubDir) {
1224
- const kiroDir = join5(hubDir, ".kiro");
1225
- const steeringDir = join5(kiroDir, "steering");
1226
- const settingsDir = join5(kiroDir, "settings");
1227
- await mkdir2(steeringDir, { recursive: true });
1228
- await mkdir2(settingsDir, { recursive: true });
1229
- const gitignoreLines = buildGitignoreLines(config);
1230
- await writeManagedFile(join5(hubDir, ".gitignore"), gitignoreLines);
1231
- console.log(chalk4.green(" Generated .gitignore"));
1232
- const kiroRule = buildKiroOrchestratorRule(config);
1233
- const kiroOrchestrator = buildKiroSteeringContent(kiroRule);
1234
- await writeFile4(join5(steeringDir, "orchestrator.md"), kiroOrchestrator, "utf-8");
1235
- console.log(chalk4.green(" Generated .kiro/steering/orchestrator.md"));
1236
- await writeFile4(join5(hubDir, "AGENTS.md"), kiroRule + "\n", "utf-8");
1237
- console.log(chalk4.green(" Generated AGENTS.md"));
1238
- const agentsDir = resolve(hubDir, "agents");
1239
- try {
1240
- const agentFiles = await readdir(agentsDir);
1241
- const mdFiles = agentFiles.filter((f) => f.endsWith(".md"));
1242
- for (const file of mdFiles) {
1243
- const agentContent = await readFile3(join5(agentsDir, file), "utf-8");
1244
- const agentName = file.replace(/\.md$/, "");
1245
- const steeringContent = buildKiroSteeringContent(agentContent, "auto", {
1246
- name: agentName,
1247
- description: `Role-specific instructions for the ${agentName} phase. Include when working on ${agentName}-related tasks.`
1248
- });
1249
- const steeringName = `agent-${file}`;
1250
- await writeFile4(join5(steeringDir, steeringName), steeringContent, "utf-8");
1251
- }
1252
- console.log(chalk4.green(` Copied ${mdFiles.length} agents as steering files`));
1253
- } catch {
1254
- console.log(chalk4.yellow(" No agents/ directory found, skipping agent copy"));
1255
- }
1256
- const skillsDir = resolve(hubDir, "skills");
1257
- try {
1258
- const skillFolders = await readdir(skillsDir);
1259
- const kiroSkillsDir = join5(kiroDir, "skills");
1260
- await mkdir2(kiroSkillsDir, { recursive: true });
1261
- let count = 0;
1262
- for (const folder of skillFolders) {
1263
- const skillFile = join5(skillsDir, folder, "SKILL.md");
1264
- try {
1265
- await readFile3(skillFile);
1266
- const srcDir = join5(skillsDir, folder);
1267
- const targetDir = join5(kiroSkillsDir, folder);
1268
- await cp(srcDir, targetDir, { recursive: true });
1269
- count++;
1270
- } catch {
1271
- }
1272
- }
1273
- if (count > 0) {
1274
- console.log(chalk4.green(` Copied ${count} skills to .kiro/skills/`));
1275
- }
1276
- } catch {
1277
- }
1278
- if (config.mcps?.length) {
1279
- const mcpConfig = {};
1280
- for (const mcp of config.mcps) {
1281
- mcpConfig[mcp.name] = buildKiroMcpEntry(mcp);
1282
- }
1283
- await writeFile4(
1284
- join5(settingsDir, "mcp.json"),
1285
- JSON.stringify({ mcpServers: mcpConfig }, null, 2) + "\n",
1286
- "utf-8"
1287
- );
1288
- console.log(chalk4.green(" Generated .kiro/settings/mcp.json"));
1289
- }
1290
- if (config.hooks) {
1291
- const hookNotes = [];
1292
- for (const [event, entries] of Object.entries(config.hooks)) {
1293
- const mapped = HOOK_EVENT_MAP[event]?.kiro;
1294
- if (!mapped) continue;
1295
- for (const entry of entries) {
1296
- hookNotes.push(`- **${mapped}**: ${entry.type === "command" ? entry.command : entry.prompt}`);
1297
- }
1298
- }
1299
- if (hookNotes.length > 0) {
1300
- console.log(chalk4.yellow(` Note: Kiro hooks are managed via the Kiro panel UI.`));
1301
- console.log(chalk4.yellow(` The following hooks should be configured manually:`));
1302
- for (const note of hookNotes) {
1303
- console.log(chalk4.yellow(` ${note}`));
1304
- }
1305
- }
1306
- }
1307
- await generateVSCodeSettings(config, hubDir);
1308
- }
1309
- async function generateVSCodeSettings(config, hubDir) {
1310
- const vscodeDir = join5(hubDir, ".vscode");
1311
- await mkdir2(vscodeDir, { recursive: true });
1312
- const settingsPath = join5(vscodeDir, "settings.json");
1313
- let existing = {};
1314
- if (existsSync3(settingsPath)) {
1315
- try {
1316
- const raw = await readFile3(settingsPath, "utf-8");
1317
- existing = JSON.parse(raw);
1318
- } catch {
1319
- existing = {};
1320
- }
1321
- }
1322
- const managed = {
1323
- "git.autoRepositoryDetection": true,
1324
- "git.detectSubmodules": true,
1325
- "git.detectSubmodulesLimit": Math.max(config.repos.length * 2, 20)
1326
- };
1327
- const merged = { ...existing, ...managed };
1328
- await writeFile4(settingsPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
1329
- console.log(chalk4.green(" Generated .vscode/settings.json (git multi-repo detection)"));
1330
- }
1331
- function buildGitignoreLines(config) {
1332
- const lines = [
1333
- "node_modules/",
1334
- ".DS_Store",
1335
- "",
1336
- "# Repositories (managed by hub)"
1337
- ];
1338
- for (const repo of config.repos) {
1339
- lines.push(repo.path.replace("./", ""));
1340
- }
1341
- lines.push(
1342
- "",
1343
- "# Docker volumes",
1344
- "*_data/",
1345
- "",
1346
- "# Environment files",
1347
- "*.env",
1348
- "*.env.local",
1349
- "!.env.example",
1350
- "",
1351
- "# Generated files",
1352
- "docker-compose.yml",
1353
- "",
1354
- "# Task documents",
1355
- "tasks/"
1356
- );
1357
- if (config.memory) {
1358
- const memPath = config.memory.path || "memories";
1359
- lines.push(
1360
- "",
1361
- "# Memory vector store (generated from markdown files)",
1362
- `${memPath}/.lancedb/`
1363
- );
1364
- }
1365
- return lines;
1366
- }
1367
- var generators = {
1368
- cursor: { name: "Cursor", generate: generateCursor },
1369
- "claude-code": { name: "Claude Code", generate: generateClaudeCode },
1370
- kiro: { name: "Kiro", generate: generateKiro }
1371
- };
1372
- var generateCommand = new Command4("generate").description("Generate editor-specific configuration files from hub.yaml").option("-e, --editor <editor>", "Target editor (cursor, claude-code, kiro)", "cursor").action(async (opts) => {
1373
- const hubDir = process.cwd();
1374
- const config = await loadHubConfig(hubDir);
1375
- if (config.memory) {
1376
- const hasMemoryMcp = config.mcps?.some(
1377
- (m) => m.name === "team-memory" || m.package === "@arvoretech/memory-mcp"
1378
- );
1379
- if (!hasMemoryMcp) {
1380
- console.log(chalk4.red(`
1381
- Error: 'memory' is configured but no memory MCP is declared in 'mcps'.
1382
- `));
1383
- console.log(chalk4.yellow(` Add this to your hub.yaml:
1384
- `));
1385
- console.log(chalk4.dim(` mcps:`));
1386
- console.log(chalk4.dim(` - name: team-memory`));
1387
- console.log(chalk4.dim(` package: "@arvoretech/memory-mcp"`));
1388
- console.log(chalk4.dim(` env:`));
1389
- console.log(chalk4.dim(` MEMORY_PATH: ${config.memory.path || "./memories"}
1390
- `));
1391
- process.exit(1);
1392
- }
1393
- }
1394
- const generator = generators[opts.editor];
1395
- if (!generator) {
1396
- console.log(
1397
- chalk4.red(`Unknown editor: ${opts.editor}. Available: ${Object.keys(generators).join(", ")}`)
1398
- );
1399
- return;
1400
- }
1401
- console.log(chalk4.blue(`
1402
- Generating ${generator.name} configuration
1403
- `));
1404
- await generator.generate(config, hubDir);
1405
- console.log(chalk4.green("\nDone!\n"));
1406
- });
1407
-
1408
- // src/commands/env.ts
1409
- import { Command as Command5 } from "commander";
1410
- import { existsSync as existsSync4 } from "fs";
1411
- import { writeFile as writeFile5, readFile as readFile4 } from "fs/promises";
1412
- import { join as join6 } from "path";
402
+ import { writeFile as writeFile4, readFile as readFile2 } from "fs/promises";
403
+ import { join as join4 } from "path";
1413
404
  import { execSync as execSync2 } from "child_process";
1414
- import chalk5 from "chalk";
405
+ import chalk4 from "chalk";
1415
406
  var authenticatedProfiles = /* @__PURE__ */ new Set();
1416
407
  function awsAuthenticated(profile) {
1417
408
  if (authenticatedProfiles.has(profile)) return true;
@@ -1458,45 +449,45 @@ function buildDatabaseUrlFromSecret(secretData, buildConfig) {
1458
449
  }
1459
450
  return `mysql://${user}:${password || ""}@${host}:${port}/${database}`;
1460
451
  }
1461
- var envCommand = new Command5("env").description("Generate environment files from hub.yaml profiles").argument("[profile]", "Environment profile (local, staging, prod)", "local").action(async (profile) => {
452
+ var envCommand = new Command4("env").description("Generate environment files from hub.yaml profiles").argument("[profile]", "Environment profile (local, staging, prod)", "local").action(async (profile) => {
1462
453
  const hubDir = process.cwd();
1463
454
  const config = await loadHubConfig(hubDir);
1464
455
  const profiles = config.env?.profiles;
1465
456
  if (!profiles) {
1466
- console.log(chalk5.yellow("\nNo env.profiles defined in hub.yaml\n"));
457
+ console.log(chalk4.yellow("\nNo env.profiles defined in hub.yaml\n"));
1467
458
  return;
1468
459
  }
1469
460
  const profileConfig = profiles[profile];
1470
461
  if (!profileConfig) {
1471
462
  const available = Object.keys(profiles).join(", ");
1472
- console.log(chalk5.red(`
463
+ console.log(chalk4.red(`
1473
464
  Unknown profile: ${profile}. Available: ${available}
1474
465
  `));
1475
466
  return;
1476
467
  }
1477
- console.log(chalk5.blue(`
468
+ console.log(chalk4.blue(`
1478
469
  \u2501\u2501\u2501 Generating environment files (${profile}) \u2501\u2501\u2501
1479
470
  `));
1480
471
  const defaultAwsProfile = profileConfig.aws_profile || "";
1481
472
  const secrets = profileConfig.secrets || {};
1482
473
  const buildDbConfigs = profileConfig.build_database_url || {};
1483
474
  if (profile !== "local" && defaultAwsProfile) {
1484
- console.log(chalk5.cyan(` Default AWS profile: ${defaultAwsProfile}`));
475
+ console.log(chalk4.cyan(` Default AWS profile: ${defaultAwsProfile}`));
1485
476
  if (!awsAuthenticated(defaultAwsProfile)) {
1486
- console.log(chalk5.red(` AWS profile ${defaultAwsProfile} not authenticated`));
1487
- console.log(chalk5.cyan(` Run: aws sso login --profile ${defaultAwsProfile}`));
477
+ console.log(chalk4.red(` AWS profile ${defaultAwsProfile} not authenticated`));
478
+ console.log(chalk4.cyan(` Run: aws sso login --profile ${defaultAwsProfile}`));
1488
479
  return;
1489
480
  }
1490
- console.log(chalk5.green(` AWS authenticated`));
481
+ console.log(chalk4.green(` AWS authenticated`));
1491
482
  }
1492
483
  for (const repo of config.repos) {
1493
484
  if (!repo.env_file) continue;
1494
- const repoDir = join6(hubDir, repo.path);
1495
- if (!existsSync4(repoDir)) {
1496
- console.log(chalk5.dim(` ${repo.name}: repo not cloned, skipping`));
485
+ const repoDir = join4(hubDir, repo.path);
486
+ if (!existsSync3(repoDir)) {
487
+ console.log(chalk4.dim(` ${repo.name}: repo not cloned, skipping`));
1497
488
  continue;
1498
489
  }
1499
- console.log(chalk5.yellow(`\u25B8 ${repo.name}`));
490
+ console.log(chalk4.yellow(`\u25B8 ${repo.name}`));
1500
491
  const envVars = {};
1501
492
  if (profile !== "local" && secrets[repo.name]) {
1502
493
  const { secretName, profile: secretProfile } = resolveSecret(
@@ -1504,20 +495,20 @@ Unknown profile: ${profile}. Available: ${available}
1504
495
  defaultAwsProfile
1505
496
  );
1506
497
  if (!secretProfile) {
1507
- console.log(chalk5.red(` No AWS profile available for secret: ${secretName}`));
498
+ console.log(chalk4.red(` No AWS profile available for secret: ${secretName}`));
1508
499
  } else {
1509
500
  if (!awsAuthenticated(secretProfile)) {
1510
- console.log(chalk5.red(` AWS profile ${secretProfile} not authenticated`));
1511
- console.log(chalk5.cyan(` Run: aws sso login --profile ${secretProfile}`));
501
+ console.log(chalk4.red(` AWS profile ${secretProfile} not authenticated`));
502
+ console.log(chalk4.cyan(` Run: aws sso login --profile ${secretProfile}`));
1512
503
  continue;
1513
504
  }
1514
- console.log(chalk5.cyan(` Fetching: ${secretName} (profile: ${secretProfile})`));
505
+ console.log(chalk4.cyan(` Fetching: ${secretName} (profile: ${secretProfile})`));
1515
506
  const secretData = fetchSecret(secretName, secretProfile);
1516
507
  if (secretData) {
1517
508
  Object.assign(envVars, secretData);
1518
- console.log(chalk5.green(` Loaded ${Object.keys(secretData).length} vars from AWS`));
509
+ console.log(chalk4.green(` Loaded ${Object.keys(secretData).length} vars from AWS`));
1519
510
  } else {
1520
- console.log(chalk5.red(` Failed to fetch secret: ${secretName}`));
511
+ console.log(chalk4.red(` Failed to fetch secret: ${secretName}`));
1521
512
  }
1522
513
  }
1523
514
  }
@@ -1525,25 +516,25 @@ Unknown profile: ${profile}. Available: ${available}
1525
516
  const buildConfig = buildDbConfigs[repo.name];
1526
517
  const dbProfile = buildConfig.profile || defaultAwsProfile;
1527
518
  if (!dbProfile) {
1528
- console.log(chalk5.red(` No AWS profile available for build_database_url`));
519
+ console.log(chalk4.red(` No AWS profile available for build_database_url`));
1529
520
  } else {
1530
521
  if (!awsAuthenticated(dbProfile)) {
1531
- console.log(chalk5.red(` AWS profile ${dbProfile} not authenticated`));
1532
- console.log(chalk5.cyan(` Run: aws sso login --profile ${dbProfile}`));
522
+ console.log(chalk4.red(` AWS profile ${dbProfile} not authenticated`));
523
+ console.log(chalk4.cyan(` Run: aws sso login --profile ${dbProfile}`));
1533
524
  } else {
1534
- console.log(chalk5.cyan(` Building DATABASE_URL from ${buildConfig.from_secret} (profile: ${dbProfile})`));
525
+ console.log(chalk4.cyan(` Building DATABASE_URL from ${buildConfig.from_secret} (profile: ${dbProfile})`));
1535
526
  const dbSecretData = fetchSecret(buildConfig.from_secret, dbProfile);
1536
527
  if (dbSecretData) {
1537
528
  const dbUrl = buildDatabaseUrlFromSecret(dbSecretData, buildConfig);
1538
529
  if (dbUrl) {
1539
530
  envVars["DATABASE_URL"] = dbUrl;
1540
531
  envVars["IDENTITY_DATABASE_URL"] = dbUrl;
1541
- console.log(chalk5.green(` Built DATABASE_URL from ${buildConfig.from_secret}`));
532
+ console.log(chalk4.green(` Built DATABASE_URL from ${buildConfig.from_secret}`));
1542
533
  } else {
1543
- console.log(chalk5.red(` Could not build DATABASE_URL - missing required fields`));
534
+ console.log(chalk4.red(` Could not build DATABASE_URL - missing required fields`));
1544
535
  }
1545
536
  } else {
1546
- console.log(chalk5.red(` Failed to fetch secret: ${buildConfig.from_secret}`));
537
+ console.log(chalk4.red(` Failed to fetch secret: ${buildConfig.from_secret}`));
1547
538
  }
1548
539
  }
1549
540
  }
@@ -1553,12 +544,12 @@ Unknown profile: ${profile}. Available: ${available}
1553
544
  for (const [key, value] of Object.entries(overrides)) {
1554
545
  envVars[key] = value;
1555
546
  }
1556
- console.log(chalk5.cyan(` Applied ${Object.keys(overrides).length} overrides`));
547
+ console.log(chalk4.cyan(` Applied ${Object.keys(overrides).length} overrides`));
1557
548
  }
1558
- const envPath = join6(repoDir, repo.env_file);
549
+ const envPath = join4(repoDir, repo.env_file);
1559
550
  const existingVars = {};
1560
551
  try {
1561
- const existing = await readFile4(envPath, "utf-8");
552
+ const existing = await readFile2(envPath, "utf-8");
1562
553
  for (const line of existing.split("\n")) {
1563
554
  const trimmed = line.trim();
1564
555
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -1571,40 +562,40 @@ Unknown profile: ${profile}. Available: ${available}
1571
562
  }
1572
563
  const merged = { ...existingVars, ...envVars };
1573
564
  const lines = Object.entries(merged).map(([k, v]) => `${k}=${v}`);
1574
- await writeFile5(envPath, lines.join("\n") + "\n", "utf-8");
1575
- console.log(chalk5.green(` Created ${repo.env_file} (${lines.length} vars)`));
565
+ await writeFile4(envPath, lines.join("\n") + "\n", "utf-8");
566
+ console.log(chalk4.green(` Created ${repo.env_file} (${lines.length} vars)`));
1576
567
  }
1577
568
  console.log();
1578
569
  if (profile === "local") {
1579
- console.log(chalk5.cyan("Using local Docker services only"));
1580
- console.log(chalk5.cyan("Run: npx @arvoretech/hub services up"));
570
+ console.log(chalk4.cyan("Using local Docker services only"));
571
+ console.log(chalk4.cyan("Run: npx @arvoretech/hub services up"));
1581
572
  } else if (profile === "prod") {
1582
- console.log(chalk5.red("WARNING: Using PRODUCTION database!"));
1583
- console.log(chalk5.red("Be careful with write operations!"));
573
+ console.log(chalk4.red("WARNING: Using PRODUCTION database!"));
574
+ console.log(chalk4.red("Be careful with write operations!"));
1584
575
  } else {
1585
- console.log(chalk5.cyan(`Using ${profile} environment`));
576
+ console.log(chalk4.cyan(`Using ${profile} environment`));
1586
577
  }
1587
578
  console.log();
1588
579
  });
1589
580
 
1590
581
  // src/commands/services.ts
1591
- import { Command as Command6 } from "commander";
1592
- import { existsSync as existsSync5 } from "fs";
1593
- import { writeFile as writeFile6 } from "fs/promises";
1594
- import { join as join7 } from "path";
582
+ import { Command as Command5 } from "commander";
583
+ import { existsSync as existsSync4 } from "fs";
584
+ import { writeFile as writeFile5 } from "fs/promises";
585
+ import { join as join5 } from "path";
1595
586
  import { execSync as execSync3 } from "child_process";
1596
- import chalk6 from "chalk";
587
+ import chalk5 from "chalk";
1597
588
  async function ensureCompose(hubDir) {
1598
- const composePath = join7(hubDir, "docker-compose.yml");
1599
- if (!existsSync5(composePath)) {
589
+ const composePath = join5(hubDir, "docker-compose.yml");
590
+ if (!existsSync4(composePath)) {
1600
591
  const config = await loadHubConfig(hubDir);
1601
592
  if (!config.services?.length) {
1602
- console.log(chalk6.yellow("No services defined in hub.yaml"));
593
+ console.log(chalk5.yellow("No services defined in hub.yaml"));
1603
594
  process.exit(1);
1604
595
  }
1605
596
  const content = generateDockerCompose(config.services);
1606
- await writeFile6(composePath, content, "utf-8");
1607
- console.log(chalk6.green("Generated docker-compose.yml"));
597
+ await writeFile5(composePath, content, "utf-8");
598
+ console.log(chalk5.green("Generated docker-compose.yml"));
1608
599
  }
1609
600
  return composePath;
1610
601
  }
@@ -1616,10 +607,10 @@ function isDockerRunning() {
1616
607
  return false;
1617
608
  }
1618
609
  }
1619
- var servicesCommand = new Command6("services").description("Manage Docker development services").argument("[action]", "up, down, restart, ps, logs, clean", "up").argument("[service...]", "Specific services (for logs)").action(async (action, serviceNames) => {
610
+ var servicesCommand = new Command5("services").description("Manage Docker development services").argument("[action]", "up, down, restart, ps, logs, clean", "up").argument("[service...]", "Specific services (for logs)").action(async (action, serviceNames) => {
1620
611
  if (!isDockerRunning()) {
1621
- console.log(chalk6.red("\nDocker daemon is not running."));
1622
- console.log(chalk6.dim("Start Docker Desktop or the Docker daemon and try again.\n"));
612
+ console.log(chalk5.red("\nDocker daemon is not running."));
613
+ console.log(chalk5.dim("Start Docker Desktop or the Docker daemon and try again.\n"));
1623
614
  return;
1624
615
  }
1625
616
  const hubDir = process.cwd();
@@ -1629,26 +620,26 @@ var servicesCommand = new Command6("services").description("Manage Docker develo
1629
620
  switch (action) {
1630
621
  case "up":
1631
622
  case "start": {
1632
- console.log(chalk6.blue("\nStarting services\n"));
623
+ console.log(chalk5.blue("\nStarting services\n"));
1633
624
  execSync3(`${compose} up -d`, { stdio: "inherit", cwd: hubDir });
1634
625
  const config = await loadHubConfig(hubDir);
1635
- console.log(chalk6.green("\nServices running:"));
626
+ console.log(chalk5.green("\nServices running:"));
1636
627
  for (const svc of config.services || []) {
1637
628
  const port = svc.port || svc.ports?.[0];
1638
- if (port) console.log(chalk6.cyan(` ${svc.name}: localhost:${port}`));
629
+ if (port) console.log(chalk5.cyan(` ${svc.name}: localhost:${port}`));
1639
630
  }
1640
631
  console.log();
1641
632
  break;
1642
633
  }
1643
634
  case "down":
1644
635
  case "stop":
1645
- console.log(chalk6.blue("\nStopping services\n"));
636
+ console.log(chalk5.blue("\nStopping services\n"));
1646
637
  execSync3(`${compose} down`, { stdio: "inherit", cwd: hubDir });
1647
- console.log(chalk6.green("\nServices stopped\n"));
638
+ console.log(chalk5.green("\nServices stopped\n"));
1648
639
  break;
1649
640
  case "restart":
1650
641
  execSync3(`${compose} restart`, { stdio: "inherit", cwd: hubDir });
1651
- console.log(chalk6.green("\nServices restarted\n"));
642
+ console.log(chalk5.green("\nServices restarted\n"));
1652
643
  break;
1653
644
  case "ps":
1654
645
  case "status":
@@ -1662,34 +653,34 @@ var servicesCommand = new Command6("services").description("Manage Docker develo
1662
653
  }
1663
654
  break;
1664
655
  case "clean":
1665
- console.log(chalk6.blue("\nCleaning services (removing volumes)\n"));
656
+ console.log(chalk5.blue("\nCleaning services (removing volumes)\n"));
1666
657
  execSync3(`${compose} down -v`, { stdio: "inherit", cwd: hubDir });
1667
- console.log(chalk6.green("\nServices and volumes removed\n"));
658
+ console.log(chalk5.green("\nServices and volumes removed\n"));
1668
659
  break;
1669
660
  default:
1670
- console.log(chalk6.red(`Unknown action: ${action}`));
661
+ console.log(chalk5.red(`Unknown action: ${action}`));
1671
662
  console.log("Usage: hub services [up|down|restart|ps|logs|clean]");
1672
663
  process.exit(1);
1673
664
  }
1674
665
  } catch {
1675
- console.log(chalk6.red("\nFailed to execute docker compose command."));
1676
- console.log(chalk6.dim("Check if Docker is running and the docker-compose.yml is valid.\n"));
666
+ console.log(chalk5.red("\nFailed to execute docker compose command."));
667
+ console.log(chalk5.dim("Check if Docker is running and the docker-compose.yml is valid.\n"));
1677
668
  }
1678
669
  });
1679
670
 
1680
671
  // src/commands/skills.ts
1681
- import { Command as Command8 } from "commander";
1682
- import { existsSync as existsSync6, statSync } from "fs";
1683
- import { mkdir as mkdir4, readdir as readdir2, readFile as readFile5, rm, cp as cp2 } from "fs/promises";
1684
- import { join as join9, resolve as resolve2 } from "path";
672
+ import { Command as Command7 } from "commander";
673
+ import { existsSync as existsSync5, statSync } from "fs";
674
+ import { mkdir as mkdir3, readdir, readFile as readFile3, rm, cp } from "fs/promises";
675
+ import { join as join7, resolve } from "path";
1685
676
  import { execSync as execSync4 } from "child_process";
1686
- import chalk8 from "chalk";
677
+ import chalk7 from "chalk";
1687
678
 
1688
679
  // src/commands/registry.ts
1689
- import { Command as Command7 } from "commander";
1690
- import { mkdir as mkdir3, writeFile as writeFile7 } from "fs/promises";
1691
- import { join as join8 } from "path";
1692
- import chalk7 from "chalk";
680
+ import { Command as Command6 } from "commander";
681
+ import { mkdir as mkdir2, writeFile as writeFile6 } from "fs/promises";
682
+ import { join as join6 } from "path";
683
+ import chalk6 from "chalk";
1693
684
  var DEFAULT_REGISTRY_REPO = process.env.HUB_REGISTRY || "arvoreeducacao/rhm";
1694
685
  var DEFAULT_BRANCH = "main";
1695
686
  async function downloadDirFromGitHub(repo, remotePath, destDir, branch = DEFAULT_BRANCH) {
@@ -1704,15 +695,15 @@ async function downloadDirFromGitHub(repo, remotePath, destDir, branch = DEFAULT
1704
695
  throw new Error(`GitHub API error: ${res.status} ${res.statusText}`);
1705
696
  }
1706
697
  const items = await res.json();
1707
- await mkdir3(destDir, { recursive: true });
698
+ await mkdir2(destDir, { recursive: true });
1708
699
  for (const item of items) {
1709
700
  if (item.type === "file" && item.download_url) {
1710
701
  const fileRes = await fetch(item.download_url);
1711
702
  if (!fileRes.ok) continue;
1712
703
  const content = await fileRes.text();
1713
- await writeFile7(join8(destDir, item.name), content, "utf-8");
704
+ await writeFile6(join6(destDir, item.name), content, "utf-8");
1714
705
  } else if (item.type === "dir") {
1715
- await downloadDirFromGitHub(repo, item.path, join8(destDir, item.name), branch);
706
+ await downloadDirFromGitHub(repo, item.path, join6(destDir, item.name), branch);
1716
707
  }
1717
708
  }
1718
709
  }
@@ -1814,10 +805,10 @@ async function listRegistryCommands(repo) {
1814
805
  return commands;
1815
806
  }
1816
807
  var TYPE_LABELS = {
1817
- skill: (t) => chalk7.green(t),
1818
- agent: (t) => chalk7.blue(t),
1819
- hook: (t) => chalk7.magenta(t),
1820
- command: (t) => chalk7.cyan(t)
808
+ skill: (t) => chalk6.green(t),
809
+ agent: (t) => chalk6.blue(t),
810
+ hook: (t) => chalk6.magenta(t),
811
+ command: (t) => chalk6.cyan(t)
1821
812
  };
1822
813
  var INSTALL_HINTS = {
1823
814
  skill: "hub skills add <name>",
@@ -1825,10 +816,10 @@ var INSTALL_HINTS = {
1825
816
  hook: "hub hooks add <name>",
1826
817
  command: "hub commands add <name>"
1827
818
  };
1828
- var registryCommand = new Command7("registry").description("Browse and install skills, agents, hooks, and commands from the registry").option("-r, --repo <repo>", "Registry repository (owner/repo)", DEFAULT_REGISTRY_REPO).addCommand(
1829
- new Command7("search").description("Search the registry").argument("[query]", "Search term").option("-t, --type <type>", "Filter by type (skill, agent, hook, command)").action(async (query, opts) => {
819
+ var registryCommand = new Command6("registry").description("Browse and install skills, agents, hooks, and commands from the registry").option("-r, --repo <repo>", "Registry repository (owner/repo)", DEFAULT_REGISTRY_REPO).addCommand(
820
+ new Command6("search").description("Search the registry").argument("[query]", "Search term").option("-t, --type <type>", "Filter by type (skill, agent, hook, command)").action(async (query, opts) => {
1830
821
  const repo = registryCommand.opts().repo || DEFAULT_REGISTRY_REPO;
1831
- console.log(chalk7.blue(`
822
+ console.log(chalk6.blue(`
1832
823
  \u2501\u2501\u2501 Hub Registry (${repo}) \u2501\u2501\u2501
1833
824
  `));
1834
825
  const results = [];
@@ -1838,7 +829,7 @@ var registryCommand = new Command7("registry").description("Browse and install s
1838
829
  const skills = await listRegistrySkills(repo);
1839
830
  for (const s of skills) results.push({ type: "skill", ...s });
1840
831
  } catch {
1841
- console.log(chalk7.yellow(" Could not fetch skills from registry."));
832
+ console.log(chalk6.yellow(" Could not fetch skills from registry."));
1842
833
  }
1843
834
  }
1844
835
  if (!typeFilter || typeFilter === "agent") {
@@ -1846,7 +837,7 @@ var registryCommand = new Command7("registry").description("Browse and install s
1846
837
  const agents = await listRegistryAgents(repo);
1847
838
  for (const a of agents) results.push({ type: "agent", ...a });
1848
839
  } catch {
1849
- console.log(chalk7.yellow(" Could not fetch agents from registry."));
840
+ console.log(chalk6.yellow(" Could not fetch agents from registry."));
1850
841
  }
1851
842
  }
1852
843
  if (!typeFilter || typeFilter === "hook") {
@@ -1854,7 +845,7 @@ var registryCommand = new Command7("registry").description("Browse and install s
1854
845
  const hooks = await listRegistryHooks(repo);
1855
846
  for (const h of hooks) results.push({ type: "hook", ...h });
1856
847
  } catch {
1857
- console.log(chalk7.yellow(" Could not fetch hooks from registry."));
848
+ console.log(chalk6.yellow(" Could not fetch hooks from registry."));
1858
849
  }
1859
850
  }
1860
851
  if (!typeFilter || typeFilter === "command") {
@@ -1862,7 +853,7 @@ var registryCommand = new Command7("registry").description("Browse and install s
1862
853
  const commands = await listRegistryCommands(repo);
1863
854
  for (const c of commands) results.push({ type: "command", ...c });
1864
855
  } catch {
1865
- console.log(chalk7.yellow(" Could not fetch commands from registry."));
856
+ console.log(chalk6.yellow(" Could not fetch commands from registry."));
1866
857
  }
1867
858
  }
1868
859
  let filtered = results;
@@ -1873,28 +864,28 @@ var registryCommand = new Command7("registry").description("Browse and install s
1873
864
  );
1874
865
  }
1875
866
  if (filtered.length === 0) {
1876
- console.log(chalk7.dim(" No results found.\n"));
867
+ console.log(chalk6.dim(" No results found.\n"));
1877
868
  return;
1878
869
  }
1879
870
  for (const entry of filtered) {
1880
871
  const labelFn = TYPE_LABELS[entry.type] || ((t) => t);
1881
- console.log(` ${labelFn(`[${entry.type}]`)} ${chalk7.yellow(entry.name)}`);
872
+ console.log(` ${labelFn(`[${entry.type}]`)} ${chalk6.yellow(entry.name)}`);
1882
873
  if (entry.description) console.log(` ${entry.description}`);
1883
874
  console.log();
1884
875
  }
1885
- console.log(chalk7.cyan(` ${filtered.length} result(s)
876
+ console.log(chalk6.cyan(` ${filtered.length} result(s)
1886
877
  `));
1887
878
  const types = [...new Set(filtered.map((e) => e.type))];
1888
879
  for (const type of types) {
1889
880
  const hint = INSTALL_HINTS[type];
1890
- if (hint) console.log(chalk7.dim(` Install ${type}: ${hint}`));
881
+ if (hint) console.log(chalk6.dim(` Install ${type}: ${hint}`));
1891
882
  }
1892
883
  console.log();
1893
884
  })
1894
885
  ).addCommand(
1895
- new Command7("list").description("List everything in the registry").option("-t, --type <type>", "Filter by type (skill, agent, hook, command)").action(async (opts) => {
886
+ new Command6("list").description("List everything in the registry").option("-t, --type <type>", "Filter by type (skill, agent, hook, command)").action(async (opts) => {
1896
887
  const repo = registryCommand.opts().repo || DEFAULT_REGISTRY_REPO;
1897
- console.log(chalk7.blue(`
888
+ console.log(chalk6.blue(`
1898
889
  \u2501\u2501\u2501 Hub Registry (${repo}) \u2501\u2501\u2501
1899
890
  `));
1900
891
  const typeFilter = opts?.type;
@@ -1902,56 +893,56 @@ var registryCommand = new Command7("registry").description("Browse and install s
1902
893
  try {
1903
894
  const skills = await listRegistrySkills(repo);
1904
895
  if (skills.length) {
1905
- console.log(chalk7.green(`Skills (${skills.length}):`));
896
+ console.log(chalk6.green(`Skills (${skills.length}):`));
1906
897
  for (const s of skills) {
1907
- console.log(` ${chalk7.yellow(s.name)}${s.description ? ` \u2014 ${s.description}` : ""}`);
898
+ console.log(` ${chalk6.yellow(s.name)}${s.description ? ` \u2014 ${s.description}` : ""}`);
1908
899
  }
1909
900
  console.log();
1910
901
  }
1911
902
  } catch {
1912
- console.log(chalk7.yellow(" Could not fetch skills.\n"));
903
+ console.log(chalk6.yellow(" Could not fetch skills.\n"));
1913
904
  }
1914
905
  }
1915
906
  if (!typeFilter || typeFilter === "agent") {
1916
907
  try {
1917
908
  const agents = await listRegistryAgents(repo);
1918
909
  if (agents.length) {
1919
- console.log(chalk7.blue(`Agents (${agents.length}):`));
910
+ console.log(chalk6.blue(`Agents (${agents.length}):`));
1920
911
  for (const a of agents) {
1921
- console.log(` ${chalk7.yellow(a.name)}${a.description ? ` \u2014 ${a.description}` : ""}`);
912
+ console.log(` ${chalk6.yellow(a.name)}${a.description ? ` \u2014 ${a.description}` : ""}`);
1922
913
  }
1923
914
  console.log();
1924
915
  }
1925
916
  } catch {
1926
- console.log(chalk7.yellow(" Could not fetch agents.\n"));
917
+ console.log(chalk6.yellow(" Could not fetch agents.\n"));
1927
918
  }
1928
919
  }
1929
920
  if (!typeFilter || typeFilter === "hook") {
1930
921
  try {
1931
922
  const hooks = await listRegistryHooks(repo);
1932
923
  if (hooks.length) {
1933
- console.log(chalk7.magenta(`Hooks (${hooks.length}):`));
924
+ console.log(chalk6.magenta(`Hooks (${hooks.length}):`));
1934
925
  for (const h of hooks) {
1935
- console.log(` ${chalk7.yellow(h.name)}${h.description ? ` \u2014 ${h.description}` : ""}`);
926
+ console.log(` ${chalk6.yellow(h.name)}${h.description ? ` \u2014 ${h.description}` : ""}`);
1936
927
  }
1937
928
  console.log();
1938
929
  }
1939
930
  } catch {
1940
- console.log(chalk7.yellow(" Could not fetch hooks.\n"));
931
+ console.log(chalk6.yellow(" Could not fetch hooks.\n"));
1941
932
  }
1942
933
  }
1943
934
  if (!typeFilter || typeFilter === "command") {
1944
935
  try {
1945
936
  const commands = await listRegistryCommands(repo);
1946
937
  if (commands.length) {
1947
- console.log(chalk7.cyan(`Commands (${commands.length}):`));
938
+ console.log(chalk6.cyan(`Commands (${commands.length}):`));
1948
939
  for (const c of commands) {
1949
- console.log(` ${chalk7.yellow(c.name)}${c.description ? ` \u2014 ${c.description}` : ""}`);
940
+ console.log(` ${chalk6.yellow(c.name)}${c.description ? ` \u2014 ${c.description}` : ""}`);
1950
941
  }
1951
942
  console.log();
1952
943
  }
1953
944
  } catch {
1954
- console.log(chalk7.yellow(" Could not fetch commands.\n"));
945
+ console.log(chalk6.yellow(" Could not fetch commands.\n"));
1955
946
  }
1956
947
  }
1957
948
  })
@@ -1960,17 +951,17 @@ var registryCommand = new Command7("registry").description("Browse and install s
1960
951
  // src/commands/skills.ts
1961
952
  var DEFAULT_REGISTRY_REPO2 = process.env.HUB_REGISTRY || "arvoreeducacao/rhm";
1962
953
  function tmpDir() {
1963
- return join9(process.env.TMPDIR || "/tmp", `hub-skills-${Date.now()}`);
954
+ return join7(process.env.TMPDIR || "/tmp", `hub-skills-${Date.now()}`);
1964
955
  }
1965
956
  async function listLocalSkills(hubDir) {
1966
- const skillsDir = join9(hubDir, "skills");
957
+ const skillsDir = join7(hubDir, "skills");
1967
958
  const skills = [];
1968
- if (!existsSync6(skillsDir)) return skills;
1969
- const folders = await readdir2(skillsDir);
959
+ if (!existsSync5(skillsDir)) return skills;
960
+ const folders = await readdir(skillsDir);
1970
961
  for (const folder of folders) {
1971
- const skillFile = join9(skillsDir, folder, "SKILL.md");
1972
- if (!existsSync6(skillFile)) continue;
1973
- const content = await readFile5(skillFile, "utf-8");
962
+ const skillFile = join7(skillsDir, folder, "SKILL.md");
963
+ if (!existsSync5(skillFile)) continue;
964
+ const content = await readFile3(skillFile, "utf-8");
1974
965
  const descMatch = content.match(/^description:\s*(.+)$/m);
1975
966
  skills.push({
1976
967
  name: folder,
@@ -1980,23 +971,23 @@ async function listLocalSkills(hubDir) {
1980
971
  return skills;
1981
972
  }
1982
973
  async function findSkillFolders(rootDir) {
1983
- const skillsDir = join9(rootDir, "skills");
1984
- if (existsSync6(skillsDir)) {
1985
- const entries = await readdir2(skillsDir);
974
+ const skillsDir = join7(rootDir, "skills");
975
+ if (existsSync5(skillsDir)) {
976
+ const entries = await readdir(skillsDir);
1986
977
  const folders = entries.filter(
1987
- (f) => existsSync6(join9(skillsDir, f, "SKILL.md"))
978
+ (f) => existsSync5(join7(skillsDir, f, "SKILL.md"))
1988
979
  );
1989
980
  if (folders.length > 0) return { dir: skillsDir, folders };
1990
981
  }
1991
- if (existsSync6(rootDir)) {
1992
- const entries = await readdir2(rootDir);
982
+ if (existsSync5(rootDir)) {
983
+ const entries = await readdir(rootDir);
1993
984
  const folders = entries.filter(
1994
- (f) => !f.startsWith(".") && f !== "node_modules" && existsSync6(join9(rootDir, f, "SKILL.md"))
985
+ (f) => !f.startsWith(".") && f !== "node_modules" && existsSync5(join7(rootDir, f, "SKILL.md"))
1995
986
  );
1996
987
  if (folders.length > 0) return { dir: rootDir, folders };
1997
988
  }
1998
- if (existsSync6(join9(rootDir, "SKILL.md"))) {
1999
- return { dir: join9(rootDir, ".."), folders: [rootDir.split("/").pop()] };
989
+ if (existsSync5(join7(rootDir, "SKILL.md"))) {
990
+ return { dir: join7(rootDir, ".."), folders: [rootDir.split("/").pop()] };
2000
991
  }
2001
992
  return { dir: skillsDir, folders: [] };
2002
993
  }
@@ -2004,24 +995,24 @@ async function installSkillsFromDir(sourceSkillsDir, hubDir, opts) {
2004
995
  const rootDir = sourceSkillsDir.endsWith("/skills") ? sourceSkillsDir.replace(/\/skills$/, "") : sourceSkillsDir;
2005
996
  const { dir, folders: skillFolders } = await findSkillFolders(rootDir);
2006
997
  if (skillFolders.length === 0) {
2007
- console.log(chalk8.red(" No skills found (looked in skills/, root dirs, and SKILL.md)"));
998
+ console.log(chalk7.red(" No skills found (looked in skills/, root dirs, and SKILL.md)"));
2008
999
  return;
2009
1000
  }
2010
1001
  const toInstall = opts.skill ? skillFolders.filter((s) => s === opts.skill) : skillFolders;
2011
1002
  if (opts.skill && toInstall.length === 0) {
2012
- console.log(chalk8.red(` Skill '${opts.skill}' not found. Available: ${skillFolders.join(", ")}`));
1003
+ console.log(chalk7.red(` Skill '${opts.skill}' not found. Available: ${skillFolders.join(", ")}`));
2013
1004
  return;
2014
1005
  }
2015
- const targetBase = opts.global ? join9(process.env.HOME || "~", ".cursor", "skills") : join9(hubDir, "skills");
2016
- await mkdir4(targetBase, { recursive: true });
1006
+ const targetBase = opts.global ? join7(process.env.HOME || "~", ".cursor", "skills") : join7(hubDir, "skills");
1007
+ await mkdir3(targetBase, { recursive: true });
2017
1008
  for (const skill of toInstall) {
2018
- const src = join9(dir, skill);
2019
- const dest = join9(targetBase, skill);
2020
- await cp2(src, dest, { recursive: true });
2021
- console.log(chalk8.green(` Installed: ${skill}`));
1009
+ const src = join7(dir, skill);
1010
+ const dest = join7(targetBase, skill);
1011
+ await cp(src, dest, { recursive: true });
1012
+ console.log(chalk7.green(` Installed: ${skill}`));
2022
1013
  }
2023
1014
  console.log(
2024
- chalk8.green(
1015
+ chalk7.green(
2025
1016
  `
2026
1017
  ${toInstall.length} skill(s) installed to ${opts.global ? "global" : "project"}
2027
1018
  `
@@ -2031,42 +1022,42 @@ async function installSkillsFromDir(sourceSkillsDir, hubDir, opts) {
2031
1022
  async function addFromRegistry(skillName, hubDir, opts) {
2032
1023
  const repo = opts.repo || DEFAULT_REGISTRY_REPO2;
2033
1024
  const remotePath = `skills/${skillName}`;
2034
- const targetBase = opts.global ? join9(process.env.HOME || "~", ".cursor", "skills") : join9(hubDir, "skills");
2035
- const dest = join9(targetBase, skillName);
2036
- console.log(chalk8.cyan(` Downloading ${skillName} from ${repo}...`));
1025
+ const targetBase = opts.global ? join7(process.env.HOME || "~", ".cursor", "skills") : join7(hubDir, "skills");
1026
+ const dest = join7(targetBase, skillName);
1027
+ console.log(chalk7.cyan(` Downloading ${skillName} from ${repo}...`));
2037
1028
  try {
2038
1029
  await downloadDirFromGitHub(repo, remotePath, dest);
2039
- if (!existsSync6(join9(dest, "SKILL.md"))) {
1030
+ if (!existsSync5(join7(dest, "SKILL.md"))) {
2040
1031
  await rm(dest, { recursive: true }).catch(() => {
2041
1032
  });
2042
- console.log(chalk8.red(` Skill '${skillName}' not found in registry (${repo})`));
2043
- console.log(chalk8.dim(" Run 'hub registry list' to see available skills."));
1033
+ console.log(chalk7.red(` Skill '${skillName}' not found in registry (${repo})`));
1034
+ console.log(chalk7.dim(" Run 'hub registry list' to see available skills."));
2044
1035
  return;
2045
1036
  }
2046
- console.log(chalk8.green(` Installed: ${skillName}`));
2047
- console.log(chalk8.green(`
1037
+ console.log(chalk7.green(` Installed: ${skillName}`));
1038
+ console.log(chalk7.green(`
2048
1039
  1 skill(s) installed to ${opts.global ? "global" : "project"}
2049
1040
  `));
2050
1041
  } catch (err) {
2051
- console.log(chalk8.red(` Failed to download skill '${skillName}': ${err.message}`));
2052
- console.log(chalk8.dim(" Run 'hub registry list' to see available skills."));
1042
+ console.log(chalk7.red(` Failed to download skill '${skillName}': ${err.message}`));
1043
+ console.log(chalk7.dim(" Run 'hub registry list' to see available skills."));
2053
1044
  }
2054
1045
  }
2055
1046
  async function addFromGitHubSkill(owner, repo, skillName, hubDir, opts) {
2056
1047
  const fullRepo = `${owner}/${repo}`;
2057
- const targetBase = opts.global ? join9(process.env.HOME || "~", ".cursor", "skills") : join9(hubDir, "skills");
2058
- const dest = join9(targetBase, skillName);
1048
+ const targetBase = opts.global ? join7(process.env.HOME || "~", ".cursor", "skills") : join7(hubDir, "skills");
1049
+ const dest = join7(targetBase, skillName);
2059
1050
  const pathsToTry = [
2060
1051
  `skills/${skillName}`,
2061
1052
  skillName
2062
1053
  ];
2063
- console.log(chalk8.cyan(` Downloading ${skillName} from ${fullRepo} via GitHub API...`));
1054
+ console.log(chalk7.cyan(` Downloading ${skillName} from ${fullRepo} via GitHub API...`));
2064
1055
  for (const remotePath of pathsToTry) {
2065
1056
  try {
2066
1057
  await downloadDirFromGitHub(fullRepo, remotePath, dest);
2067
- if (existsSync6(join9(dest, "SKILL.md"))) {
2068
- console.log(chalk8.green(` Installed: ${skillName} (from ${fullRepo})`));
2069
- console.log(chalk8.green(`
1058
+ if (existsSync5(join7(dest, "SKILL.md"))) {
1059
+ console.log(chalk7.green(` Installed: ${skillName} (from ${fullRepo})`));
1060
+ console.log(chalk7.green(`
2070
1061
  1 skill(s) installed to ${opts.global ? "global" : "project"}
2071
1062
  `));
2072
1063
  return;
@@ -2078,12 +1069,12 @@ async function addFromGitHubSkill(owner, repo, skillName, hubDir, opts) {
2078
1069
  });
2079
1070
  }
2080
1071
  }
2081
- console.log(chalk8.red(` Skill '${skillName}' not found in ${fullRepo}`));
2082
- console.log(chalk8.dim(` Check available skills: hub skills add ${fullRepo} --list`));
1072
+ console.log(chalk7.red(` Skill '${skillName}' not found in ${fullRepo}`));
1073
+ console.log(chalk7.dim(` Check available skills: hub skills add ${fullRepo} --list`));
2083
1074
  }
2084
1075
  async function listRemoteSkills(owner, repo) {
2085
1076
  const fullRepo = `${owner}/${repo}`;
2086
- console.log(chalk8.cyan(` Fetching skills from ${fullRepo}...
1077
+ console.log(chalk7.cyan(` Fetching skills from ${fullRepo}...
2087
1078
  `));
2088
1079
  const headers = { Accept: "application/vnd.github.v3+json" };
2089
1080
  try {
@@ -2121,38 +1112,38 @@ async function listRemoteSkills(owner, repo) {
2121
1112
  { headers }
2122
1113
  );
2123
1114
  if (rootSkill.ok) {
2124
- console.log(chalk8.green(` This repo is a single skill.
1115
+ console.log(chalk7.green(` This repo is a single skill.
2125
1116
  `));
2126
- console.log(chalk8.dim(` Install with: hub skills add ${fullRepo}
1117
+ console.log(chalk7.dim(` Install with: hub skills add ${fullRepo}
2127
1118
  `));
2128
1119
  return;
2129
1120
  }
2130
1121
  }
2131
1122
  if (dirs.length === 0) {
2132
- console.log(chalk8.dim(" No skills found."));
1123
+ console.log(chalk7.dim(" No skills found."));
2133
1124
  return;
2134
1125
  }
2135
- console.log(chalk8.green(` Available skills (${dirs.length}):
1126
+ console.log(chalk7.green(` Available skills (${dirs.length}):
2136
1127
  `));
2137
1128
  for (const dir of dirs) {
2138
- console.log(` ${chalk8.yellow(dir.name)}`);
1129
+ console.log(` ${chalk7.yellow(dir.name)}`);
2139
1130
  }
2140
- console.log(chalk8.dim(`
1131
+ console.log(chalk7.dim(`
2141
1132
  Install with: hub skills add ${fullRepo}/<skill-name>`));
2142
- console.log(chalk8.dim(` Install all: hub skills add ${fullRepo}
1133
+ console.log(chalk7.dim(` Install all: hub skills add ${fullRepo}
2143
1134
  `));
2144
1135
  } catch {
2145
- console.log(chalk8.red(` Failed to fetch skill list from ${fullRepo}`));
1136
+ console.log(chalk7.red(` Failed to fetch skill list from ${fullRepo}`));
2146
1137
  }
2147
1138
  }
2148
1139
  async function addFromLocalPath(localPath, hubDir, opts) {
2149
- const absPath = resolve2(localPath);
2150
- if (!existsSync6(absPath)) {
2151
- console.log(chalk8.red(` Path not found: ${absPath}`));
1140
+ const absPath = resolve(localPath);
1141
+ if (!existsSync5(absPath)) {
1142
+ console.log(chalk7.red(` Path not found: ${absPath}`));
2152
1143
  return;
2153
1144
  }
2154
1145
  if (!statSync(absPath).isDirectory()) {
2155
- console.log(chalk8.red(` Path is not a directory: ${absPath}`));
1146
+ console.log(chalk7.red(` Path is not a directory: ${absPath}`));
2156
1147
  return;
2157
1148
  }
2158
1149
  await installSkillsFromDir(absPath, hubDir, opts);
@@ -2160,19 +1151,19 @@ async function addFromLocalPath(localPath, hubDir, opts) {
2160
1151
  async function addFromGitRepo(source, hubDir, opts) {
2161
1152
  const tmp = tmpDir();
2162
1153
  try {
2163
- console.log(chalk8.cyan(` Cloning ${source}...`));
1154
+ console.log(chalk7.cyan(` Cloning ${source}...`));
2164
1155
  try {
2165
1156
  execSync4(`git clone --depth 1 ${source} ${tmp}`, {
2166
1157
  stdio: ["pipe", "pipe", "pipe"]
2167
1158
  });
2168
1159
  } catch {
2169
- console.log(chalk8.red(` Repository not found or not accessible: ${source}`));
2170
- console.log(chalk8.dim(" Make sure the URL is correct and you have access to the repository."));
1160
+ console.log(chalk7.red(` Repository not found or not accessible: ${source}`));
1161
+ console.log(chalk7.dim(" Make sure the URL is correct and you have access to the repository."));
2171
1162
  return;
2172
1163
  }
2173
1164
  await installSkillsFromDir(tmp, hubDir, opts);
2174
1165
  } finally {
2175
- if (existsSync6(tmp)) {
1166
+ if (existsSync5(tmp)) {
2176
1167
  await rm(tmp, { recursive: true });
2177
1168
  }
2178
1169
  }
@@ -2186,124 +1177,130 @@ function parseGitHubSource(source) {
2186
1177
  if (parts.length === 3) return { owner: parts[0], repo: parts[1], skill: parts[2] };
2187
1178
  return null;
2188
1179
  }
2189
- var skillsCommand = new Command8("skills").description("Manage agent skills").addCommand(
2190
- new Command8("add").description("Install skills from registry, GitHub, git URL, or local path").argument("<source>", "Skill name, owner/repo, owner/repo/skill, git URL, or local path").option("-s, --skill <name>", "Install a specific skill only (for repo sources)").option("-g, --global", "Install to global ~/.cursor/skills/").option("-r, --repo <repo>", "Registry repository (owner/repo)").option("-l, --list", "List available skills without installing").action(async (source, opts) => {
1180
+ var skillsCommand = new Command7("skills").description("Manage agent skills").addCommand(
1181
+ new Command7("add").description("Install skills from registry, GitHub, git URL, or local path").argument("<source>", "Skill name, owner/repo, owner/repo/skill, git URL, or local path").option("-s, --skill <name>", "Install a specific skill only (for repo sources)").option("-g, --global", "Install to global ~/.cursor/skills/").option("-r, --repo <repo>", "Registry repository (owner/repo)").option("-l, --list", "List available skills without installing").action(async (source, opts) => {
2191
1182
  const hubDir = process.cwd();
2192
1183
  if (isLocalPath(source)) {
2193
- console.log(chalk8.blue(`
1184
+ console.log(chalk7.blue(`
2194
1185
  Installing skills from ${source}
2195
1186
  `));
2196
1187
  await addFromLocalPath(source, hubDir, opts);
1188
+ if (!opts.global) await checkAndAutoRegenerate(hubDir);
2197
1189
  return;
2198
1190
  }
2199
1191
  if (source.startsWith("git@") || source.startsWith("https://")) {
2200
- console.log(chalk8.blue(`
1192
+ console.log(chalk7.blue(`
2201
1193
  Installing skills from ${source}
2202
1194
  `));
2203
1195
  await addFromGitRepo(source, hubDir, opts);
1196
+ if (!opts.global) await checkAndAutoRegenerate(hubDir);
2204
1197
  return;
2205
1198
  }
2206
1199
  const parsed = parseGitHubSource(source);
2207
1200
  if (parsed && opts.list) {
2208
- console.log(chalk8.blue(`
1201
+ console.log(chalk7.blue(`
2209
1202
  Listing skills from ${parsed.owner}/${parsed.repo}
2210
1203
  `));
2211
1204
  await listRemoteSkills(parsed.owner, parsed.repo);
2212
1205
  return;
2213
1206
  }
2214
1207
  if (parsed?.skill) {
2215
- console.log(chalk8.blue(`
1208
+ console.log(chalk7.blue(`
2216
1209
  Installing skill ${parsed.skill} from ${parsed.owner}/${parsed.repo}
2217
1210
  `));
2218
1211
  await addFromGitHubSkill(parsed.owner, parsed.repo, parsed.skill, hubDir, opts);
1212
+ if (!opts.global) await checkAndAutoRegenerate(hubDir);
2219
1213
  return;
2220
1214
  }
2221
1215
  if (parsed && !parsed.skill) {
2222
- console.log(chalk8.blue(`
1216
+ console.log(chalk7.blue(`
2223
1217
  Installing skills from ${source}
2224
1218
  `));
2225
1219
  const url = `https://github.com/${source}.git`;
2226
1220
  await addFromGitRepo(url, hubDir, opts);
1221
+ if (!opts.global) await checkAndAutoRegenerate(hubDir);
2227
1222
  return;
2228
1223
  }
2229
- console.log(chalk8.blue(`
1224
+ console.log(chalk7.blue(`
2230
1225
  Installing skill ${source} from registry
2231
1226
  `));
2232
1227
  await addFromRegistry(source, hubDir, opts);
1228
+ if (!opts.global) await checkAndAutoRegenerate(hubDir);
2233
1229
  })
2234
1230
  ).addCommand(
2235
- new Command8("find").description("Browse curated skills in the Repo Hub directory").argument("[query]", "Search term").action(async (query) => {
2236
- const base = "https://rhm-website.vercel.app/directory?type=skill";
1231
+ new Command7("find").description("Browse curated skills in the Repo Hub directory").argument("[query]", "Search term").action(async (query) => {
1232
+ const base = "https://hub.arvore.com.br/directory?type=skill";
2237
1233
  const url = query ? `${base}&q=${encodeURIComponent(query)}` : base;
2238
- console.log(chalk8.blue("\n Browse curated skills at:\n"));
2239
- console.log(chalk8.cyan(` ${url}
1234
+ console.log(chalk7.blue("\n Browse curated skills at:\n"));
1235
+ console.log(chalk7.cyan(` ${url}
2240
1236
  `));
2241
- console.log(chalk8.dim(" Install with: hub skills add <owner>/<repo>/<skill-name>"));
2242
- console.log(chalk8.dim(" Example: hub skills add vercel-labs/agent-skills/react-best-practices\n"));
1237
+ console.log(chalk7.dim(" Install with: hub skills add <owner>/<repo>/<skill-name>"));
1238
+ console.log(chalk7.dim(" Example: hub skills add vercel-labs/agent-skills/react-best-practices\n"));
2243
1239
  })
2244
1240
  ).addCommand(
2245
- new Command8("list").description("List installed skills").action(async () => {
1241
+ new Command7("list").description("List installed skills").action(async () => {
2246
1242
  const hubDir = process.cwd();
2247
- console.log(chalk8.blue("\nInstalled skills\n"));
1243
+ console.log(chalk7.blue("\nInstalled skills\n"));
2248
1244
  const projectSkills = await listLocalSkills(hubDir);
2249
1245
  if (projectSkills.length > 0) {
2250
- console.log(chalk8.cyan("Project:"));
1246
+ console.log(chalk7.cyan("Project:"));
2251
1247
  for (const s of projectSkills) {
2252
- console.log(` ${chalk8.yellow(s.name)} \u2014 ${s.description}`);
1248
+ console.log(` ${chalk7.yellow(s.name)} \u2014 ${s.description}`);
2253
1249
  }
2254
1250
  } else {
2255
- console.log(chalk8.dim(" No project skills (skills/)"));
1251
+ console.log(chalk7.dim(" No project skills (skills/)"));
2256
1252
  }
2257
- const globalDir = join9(process.env.HOME || "~", ".cursor", "skills");
2258
- const globalSkills = await listLocalSkills(join9(globalDir, ".."));
1253
+ const globalDir = join7(process.env.HOME || "~", ".cursor", "skills");
1254
+ const globalSkills = await listLocalSkills(join7(globalDir, ".."));
2259
1255
  console.log();
2260
1256
  if (globalSkills.length > 0) {
2261
- console.log(chalk8.cyan("Global:"));
1257
+ console.log(chalk7.cyan("Global:"));
2262
1258
  for (const s of globalSkills) {
2263
- console.log(` ${chalk8.yellow(s.name)} \u2014 ${s.description}`);
1259
+ console.log(` ${chalk7.yellow(s.name)} \u2014 ${s.description}`);
2264
1260
  }
2265
1261
  } else {
2266
- console.log(chalk8.dim(" No global skills (~/.cursor/skills/)"));
1262
+ console.log(chalk7.dim(" No global skills (~/.cursor/skills/)"));
2267
1263
  }
2268
1264
  console.log();
2269
1265
  })
2270
1266
  ).addCommand(
2271
- new Command8("remove").description("Remove a skill").argument("<name>", "Skill name to remove").option("-g, --global", "Remove from global skills").action(async (name, opts) => {
1267
+ new Command7("remove").description("Remove a skill").argument("<name>", "Skill name to remove").option("-g, --global", "Remove from global skills").action(async (name, opts) => {
2272
1268
  const hubDir = process.cwd();
2273
- const base = opts.global ? join9(process.env.HOME || "~", ".cursor", "skills") : join9(hubDir, "skills");
2274
- const target = join9(base, name);
2275
- if (!existsSync6(target)) {
2276
- console.log(chalk8.red(`
1269
+ const base = opts.global ? join7(process.env.HOME || "~", ".cursor", "skills") : join7(hubDir, "skills");
1270
+ const target = join7(base, name);
1271
+ if (!existsSync5(target)) {
1272
+ console.log(chalk7.red(`
2277
1273
  Skill '${name}' not found in ${opts.global ? "global" : "project"}
2278
1274
  `));
2279
1275
  return;
2280
1276
  }
2281
1277
  await rm(target, { recursive: true });
2282
- console.log(chalk8.green(`
1278
+ console.log(chalk7.green(`
2283
1279
  Removed skill: ${name}
2284
1280
  `));
1281
+ if (!opts.global) await checkAndAutoRegenerate(hubDir);
2285
1282
  })
2286
1283
  );
2287
1284
 
2288
1285
  // src/commands/agents.ts
2289
- import { Command as Command9 } from "commander";
2290
- import { existsSync as existsSync7, statSync as statSync2 } from "fs";
2291
- import { mkdir as mkdir5, readdir as readdir3, readFile as readFile6, rm as rm2, copyFile as copyFile2, writeFile as writeFile8 } from "fs/promises";
2292
- import { join as join10, resolve as resolve3 } from "path";
1286
+ import { Command as Command8 } from "commander";
1287
+ import { existsSync as existsSync6, statSync as statSync2 } from "fs";
1288
+ import { mkdir as mkdir4, readdir as readdir2, readFile as readFile4, rm as rm2, copyFile, writeFile as writeFile7 } from "fs/promises";
1289
+ import { join as join8, resolve as resolve2 } from "path";
2293
1290
  import { execSync as execSync5 } from "child_process";
2294
- import chalk9 from "chalk";
1291
+ import chalk8 from "chalk";
2295
1292
  var DEFAULT_REGISTRY_REPO3 = process.env.HUB_REGISTRY || "arvoreeducacao/rhm";
2296
1293
  var DEFAULT_BRANCH2 = "main";
2297
1294
  function tmpDir2() {
2298
- return join10(process.env.TMPDIR || "/tmp", `hub-agents-${Date.now()}`);
1295
+ return join8(process.env.TMPDIR || "/tmp", `hub-agents-${Date.now()}`);
2299
1296
  }
2300
1297
  async function listLocalAgents(agentsDir) {
2301
1298
  const agents = [];
2302
- if (!existsSync7(agentsDir)) return agents;
2303
- const files = await readdir3(agentsDir);
1299
+ if (!existsSync6(agentsDir)) return agents;
1300
+ const files = await readdir2(agentsDir);
2304
1301
  for (const file of files) {
2305
1302
  if (!file.endsWith(".md")) continue;
2306
- const content = await readFile6(join10(agentsDir, file), "utf-8");
1303
+ const content = await readFile4(join8(agentsDir, file), "utf-8");
2307
1304
  const descMatch = content.match(/^description:\s*(.+)$/m);
2308
1305
  agents.push({
2309
1306
  name: file.replace(/\.md$/, ""),
@@ -2316,47 +1313,47 @@ async function addFromRegistry2(agentName, hubDir, opts) {
2316
1313
  const repo = opts.repo || DEFAULT_REGISTRY_REPO3;
2317
1314
  const fileName = agentName.endsWith(".md") ? agentName : `${agentName}.md`;
2318
1315
  const rawUrl = `https://raw.githubusercontent.com/${repo}/${DEFAULT_BRANCH2}/agents/${fileName}`;
2319
- console.log(chalk9.cyan(` Downloading ${agentName} from ${repo}...`));
1316
+ console.log(chalk8.cyan(` Downloading ${agentName} from ${repo}...`));
2320
1317
  try {
2321
1318
  const res = await fetch(rawUrl);
2322
1319
  if (!res.ok) {
2323
- console.log(chalk9.red(` Agent '${agentName}' not found in registry (${repo})`));
2324
- console.log(chalk9.dim(" Run 'hub registry list' to see available agents."));
1320
+ console.log(chalk8.red(` Agent '${agentName}' not found in registry (${repo})`));
1321
+ console.log(chalk8.dim(" Run 'hub registry list' to see available agents."));
2325
1322
  return;
2326
1323
  }
2327
1324
  const content = await res.text();
2328
- const targetBase = opts.global ? join10(process.env.HOME || "~", ".cursor", "agents") : join10(hubDir, "agents");
2329
- await mkdir5(targetBase, { recursive: true });
2330
- await writeFile8(join10(targetBase, fileName), content, "utf-8");
2331
- console.log(chalk9.green(` Installed: ${agentName}`));
2332
- console.log(chalk9.green(`
1325
+ const targetBase = opts.global ? join8(process.env.HOME || "~", ".cursor", "agents") : join8(hubDir, "agents");
1326
+ await mkdir4(targetBase, { recursive: true });
1327
+ await writeFile7(join8(targetBase, fileName), content, "utf-8");
1328
+ console.log(chalk8.green(` Installed: ${agentName}`));
1329
+ console.log(chalk8.green(`
2333
1330
  1 agent(s) installed to ${opts.global ? "global" : "project"}
2334
1331
  `));
2335
1332
  } catch (err) {
2336
- console.log(chalk9.red(` Failed to download agent '${agentName}': ${err.message}`));
1333
+ console.log(chalk8.red(` Failed to download agent '${agentName}': ${err.message}`));
2337
1334
  }
2338
1335
  }
2339
1336
  async function addFromLocalPath2(localPath, hubDir, opts) {
2340
- const absPath = resolve3(localPath);
2341
- if (!existsSync7(absPath)) {
2342
- console.log(chalk9.red(` Path not found: ${absPath}`));
1337
+ const absPath = resolve2(localPath);
1338
+ if (!existsSync6(absPath)) {
1339
+ console.log(chalk8.red(` Path not found: ${absPath}`));
2343
1340
  return;
2344
1341
  }
2345
1342
  if (!statSync2(absPath).isDirectory()) {
2346
- console.log(chalk9.red(` Path is not a directory: ${absPath}`));
1343
+ console.log(chalk8.red(` Path is not a directory: ${absPath}`));
2347
1344
  return;
2348
1345
  }
2349
1346
  await installAgentsFromDir(absPath, hubDir, opts);
2350
1347
  }
2351
1348
  async function findAgentFiles(rootDir) {
2352
- const agentsDir = join10(rootDir, "agents");
2353
- if (existsSync7(agentsDir)) {
2354
- const entries = await readdir3(agentsDir);
1349
+ const agentsDir = join8(rootDir, "agents");
1350
+ if (existsSync6(agentsDir)) {
1351
+ const entries = await readdir2(agentsDir);
2355
1352
  const mdFiles = entries.filter((f) => f.endsWith(".md"));
2356
1353
  if (mdFiles.length > 0) return { dir: agentsDir, files: mdFiles };
2357
1354
  }
2358
- if (existsSync7(rootDir)) {
2359
- const entries = await readdir3(rootDir);
1355
+ if (existsSync6(rootDir)) {
1356
+ const entries = await readdir2(rootDir);
2360
1357
  const mdFiles = entries.filter(
2361
1358
  (f) => f.endsWith(".md") && !f.startsWith(".") && f !== "README.md" && f !== "CHANGELOG.md"
2362
1359
  );
@@ -2368,23 +1365,23 @@ async function installAgentsFromDir(sourceDir, hubDir, opts) {
2368
1365
  const rootDir = sourceDir.endsWith("/agents") ? sourceDir.replace(/\/agents$/, "") : sourceDir;
2369
1366
  const { dir, files: mdFiles } = await findAgentFiles(rootDir);
2370
1367
  if (mdFiles.length === 0) {
2371
- console.log(chalk9.red(" No agent files found (looked in agents/ and root .md files)"));
1368
+ console.log(chalk8.red(" No agent files found (looked in agents/ and root .md files)"));
2372
1369
  return;
2373
1370
  }
2374
1371
  const toInstall = opts.agent ? mdFiles.filter((f) => f === `${opts.agent}.md` || f === opts.agent) : mdFiles;
2375
1372
  if (opts.agent && toInstall.length === 0) {
2376
1373
  const available = mdFiles.map((f) => f.replace(/\.md$/, "")).join(", ");
2377
- console.log(chalk9.red(` Agent '${opts.agent}' not found. Available: ${available}`));
1374
+ console.log(chalk8.red(` Agent '${opts.agent}' not found. Available: ${available}`));
2378
1375
  return;
2379
1376
  }
2380
- const targetBase = opts.global ? join10(process.env.HOME || "~", ".cursor", "agents") : join10(hubDir, "agents");
2381
- await mkdir5(targetBase, { recursive: true });
1377
+ const targetBase = opts.global ? join8(process.env.HOME || "~", ".cursor", "agents") : join8(hubDir, "agents");
1378
+ await mkdir4(targetBase, { recursive: true });
2382
1379
  for (const file of toInstall) {
2383
- await copyFile2(join10(dir, file), join10(targetBase, file));
2384
- console.log(chalk9.green(` Installed: ${file.replace(/\.md$/, "")}`));
1380
+ await copyFile(join8(dir, file), join8(targetBase, file));
1381
+ console.log(chalk8.green(` Installed: ${file.replace(/\.md$/, "")}`));
2385
1382
  }
2386
1383
  console.log(
2387
- chalk9.green(
1384
+ chalk8.green(
2388
1385
  `
2389
1386
  ${toInstall.length} agent(s) installed to ${opts.global ? "global" : "project"}
2390
1387
  `
@@ -2394,18 +1391,18 @@ async function installAgentsFromDir(sourceDir, hubDir, opts) {
2394
1391
  async function addFromGitRepo2(source, hubDir, opts) {
2395
1392
  const tmp = tmpDir2();
2396
1393
  try {
2397
- console.log(chalk9.cyan(` Cloning ${source}...`));
1394
+ console.log(chalk8.cyan(` Cloning ${source}...`));
2398
1395
  try {
2399
1396
  execSync5(`git clone --depth 1 ${source} ${tmp}`, {
2400
1397
  stdio: ["pipe", "pipe", "pipe"]
2401
1398
  });
2402
1399
  } catch {
2403
- console.log(chalk9.red(` Repository not found or not accessible: ${source}`));
1400
+ console.log(chalk8.red(` Repository not found or not accessible: ${source}`));
2404
1401
  return;
2405
1402
  }
2406
1403
  await installAgentsFromDir(tmp, hubDir, opts);
2407
1404
  } finally {
2408
- if (existsSync7(tmp)) {
1405
+ if (existsSync6(tmp)) {
2409
1406
  await rm2(tmp, { recursive: true });
2410
1407
  }
2411
1408
  }
@@ -2416,10 +1413,10 @@ function isLocalPath2(source) {
2416
1413
  function isRepoReference(source) {
2417
1414
  return source.startsWith("git@") || source.startsWith("https://") || source.includes("/");
2418
1415
  }
2419
- var agentsCommand = new Command9("agents").description("Manage agent definitions").addCommand(
2420
- new Command9("add").description("Install agents from the registry, a git repository, or local path").argument("<source>", "Agent name (from registry), GitHub shorthand (org/repo), git URL, or local path").option("-a, --agent <name>", "Install a specific agent only (for repo sources)").option("-g, --global", "Install to global ~/.cursor/agents/").option("-r, --repo <repo>", "Registry repository (owner/repo)").action(async (source, opts) => {
1416
+ var agentsCommand = new Command8("agents").description("Manage agent definitions").addCommand(
1417
+ new Command8("add").description("Install agents from the registry, a git repository, or local path").argument("<source>", "Agent name (from registry), GitHub shorthand (org/repo), git URL, or local path").option("-a, --agent <name>", "Install a specific agent only (for repo sources)").option("-g, --global", "Install to global ~/.cursor/agents/").option("-r, --repo <repo>", "Registry repository (owner/repo)").action(async (source, opts) => {
2421
1418
  const hubDir = process.cwd();
2422
- console.log(chalk9.blue(`
1419
+ console.log(chalk8.blue(`
2423
1420
  Installing agents from ${source}
2424
1421
  `));
2425
1422
  if (isLocalPath2(source)) {
@@ -2434,68 +1431,70 @@ Installing agents from ${source}
2434
1431
  } else {
2435
1432
  await addFromRegistry2(source, hubDir, opts);
2436
1433
  }
1434
+ if (!opts.global) await checkAndAutoRegenerate(hubDir);
2437
1435
  })
2438
1436
  ).addCommand(
2439
- new Command9("list").description("List installed agents").action(async () => {
1437
+ new Command8("list").description("List installed agents").action(async () => {
2440
1438
  const hubDir = process.cwd();
2441
- console.log(chalk9.blue("\nInstalled agents\n"));
2442
- const projectAgents = await listLocalAgents(join10(hubDir, "agents"));
1439
+ console.log(chalk8.blue("\nInstalled agents\n"));
1440
+ const projectAgents = await listLocalAgents(join8(hubDir, "agents"));
2443
1441
  if (projectAgents.length > 0) {
2444
- console.log(chalk9.cyan("Project:"));
1442
+ console.log(chalk8.cyan("Project:"));
2445
1443
  for (const a of projectAgents) {
2446
- console.log(` ${chalk9.yellow(a.name)}${a.description ? ` \u2014 ${a.description}` : ""}`);
1444
+ console.log(` ${chalk8.yellow(a.name)}${a.description ? ` \u2014 ${a.description}` : ""}`);
2447
1445
  }
2448
1446
  } else {
2449
- console.log(chalk9.dim(" No project agents (agents/)"));
1447
+ console.log(chalk8.dim(" No project agents (agents/)"));
2450
1448
  }
2451
- const globalDir = join10(process.env.HOME || "~", ".cursor", "agents");
1449
+ const globalDir = join8(process.env.HOME || "~", ".cursor", "agents");
2452
1450
  const globalAgents = await listLocalAgents(globalDir);
2453
1451
  console.log();
2454
1452
  if (globalAgents.length > 0) {
2455
- console.log(chalk9.cyan("Global:"));
1453
+ console.log(chalk8.cyan("Global:"));
2456
1454
  for (const a of globalAgents) {
2457
- console.log(` ${chalk9.yellow(a.name)}${a.description ? ` \u2014 ${a.description}` : ""}`);
1455
+ console.log(` ${chalk8.yellow(a.name)}${a.description ? ` \u2014 ${a.description}` : ""}`);
2458
1456
  }
2459
1457
  } else {
2460
- console.log(chalk9.dim(" No global agents (~/.cursor/agents/)"));
1458
+ console.log(chalk8.dim(" No global agents (~/.cursor/agents/)"));
2461
1459
  }
2462
1460
  console.log();
2463
1461
  })
2464
1462
  ).addCommand(
2465
- new Command9("remove").description("Remove an agent").argument("<name>", "Agent name to remove").option("-g, --global", "Remove from global agents").action(async (name, opts) => {
1463
+ new Command8("remove").description("Remove an agent").argument("<name>", "Agent name to remove").option("-g, --global", "Remove from global agents").action(async (name, opts) => {
2466
1464
  const hubDir = process.cwd();
2467
- const base = opts.global ? join10(process.env.HOME || "~", ".cursor", "agents") : join10(hubDir, "agents");
1465
+ const base = opts.global ? join8(process.env.HOME || "~", ".cursor", "agents") : join8(hubDir, "agents");
2468
1466
  const fileName = name.endsWith(".md") ? name : `${name}.md`;
2469
- const target = join10(base, fileName);
2470
- if (!existsSync7(target)) {
2471
- console.log(chalk9.red(`
1467
+ const target = join8(base, fileName);
1468
+ if (!existsSync6(target)) {
1469
+ console.log(chalk8.red(`
2472
1470
  Agent '${name}' not found in ${opts.global ? "global" : "project"}
2473
1471
  `));
2474
1472
  return;
2475
1473
  }
2476
1474
  await rm2(target);
2477
- console.log(chalk9.green(`
1475
+ console.log(chalk8.green(`
2478
1476
  Removed agent: ${name}
2479
1477
  `));
1478
+ if (!opts.global) await checkAndAutoRegenerate(hubDir);
2480
1479
  })
2481
1480
  ).addCommand(
2482
- new Command9("find").description("Browse curated agents in the Repo Hub directory").argument("[query]", "Search term").action(async (query) => {
2483
- const base = "https://rhm-website.vercel.app/directory?type=agent";
1481
+ new Command8("find").description("Browse curated agents in the Repo Hub directory").argument("[query]", "Search term").action(async (query) => {
1482
+ const base = "https://hub.arvore.com.br/directory?type=agent";
2484
1483
  const url = query ? `${base}&q=${encodeURIComponent(query)}` : base;
2485
- console.log(chalk9.blue("\n Browse curated agents at:\n"));
2486
- console.log(chalk9.cyan(` ${url}
1484
+ console.log(chalk8.blue("\n Browse curated agents at:\n"));
1485
+ console.log(chalk8.cyan(` ${url}
2487
1486
  `));
2488
- console.log(chalk9.dim(" Install with: hub agents add <owner>/<repo>"));
2489
- console.log(chalk9.dim(" Example: hub agents add my-org/my-agents\n"));
1487
+ console.log(chalk8.dim(" Install with: hub agents add <owner>/<repo>"));
1488
+ console.log(chalk8.dim(" Example: hub agents add my-org/my-agents\n"));
2490
1489
  })
2491
1490
  ).addCommand(
2492
- new Command9("sync").description("Install all agents referenced in hub.yaml from the registry").option("-g, --global", "Install to global ~/.cursor/agents/").option("-r, --repo <repo>", "Registry repository (owner/repo)").option("-f, --force", "Re-install even if the agent already exists locally").action(async (opts) => {
1491
+ new Command8("sync").description("Install all agents referenced in hub.yaml from the registry").option("-g, --global", "Install to global ~/.cursor/agents/").option("-r, --repo <repo>", "Registry repository (owner/repo)").option("-f, --force", "Re-install even if the agent already exists locally").action(async (opts) => {
2493
1492
  const hubDir = process.cwd();
2494
1493
  let config;
2495
1494
  try {
2496
1495
  config = await loadHubConfig(hubDir);
2497
1496
  } catch {
2498
- console.log(chalk9.red("\n Could not load hub.yaml in the current directory.\n"));
1497
+ console.log(chalk8.red("\n Could not load hub.yaml in the current directory.\n"));
2499
1498
  return;
2500
1499
  }
2501
1500
  const steps = config.workflow?.pipeline || [];
@@ -2509,20 +1508,20 @@ Removed agent: ${name}
2509
1508
  }
2510
1509
  }
2511
1510
  if (agentNames.size === 0) {
2512
- console.log(chalk9.yellow("\n No agents found in hub.yaml workflow pipeline.\n"));
1511
+ console.log(chalk8.yellow("\n No agents found in hub.yaml workflow pipeline.\n"));
2513
1512
  return;
2514
1513
  }
2515
- console.log(chalk9.blue(`
1514
+ console.log(chalk8.blue(`
2516
1515
  \u2501\u2501\u2501 Syncing ${agentNames.size} agent(s) from hub.yaml \u2501\u2501\u2501
2517
1516
  `));
2518
- const targetBase = opts.global ? join10(process.env.HOME || "~", ".cursor", "agents") : join10(hubDir, "agents");
1517
+ const targetBase = opts.global ? join8(process.env.HOME || "~", ".cursor", "agents") : join8(hubDir, "agents");
2519
1518
  let installed = 0;
2520
1519
  let skipped = 0;
2521
1520
  for (const name of agentNames) {
2522
1521
  const fileName = name.endsWith(".md") ? name : `${name}.md`;
2523
- const targetPath = join10(targetBase, fileName);
2524
- if (!opts.force && existsSync7(targetPath)) {
2525
- console.log(chalk9.dim(` \u2713 ${name} (already installed)`));
1522
+ const targetPath = join8(targetBase, fileName);
1523
+ if (!opts.force && existsSync6(targetPath)) {
1524
+ console.log(chalk8.dim(` \u2713 ${name} (already installed)`));
2526
1525
  skipped++;
2527
1526
  continue;
2528
1527
  }
@@ -2530,40 +1529,41 @@ Removed agent: ${name}
2530
1529
  installed++;
2531
1530
  }
2532
1531
  console.log();
2533
- if (installed > 0) console.log(chalk9.green(` ${installed} agent(s) installed`));
2534
- if (skipped > 0) console.log(chalk9.dim(` ${skipped} agent(s) already up to date`));
1532
+ if (installed > 0) console.log(chalk8.green(` ${installed} agent(s) installed`));
1533
+ if (skipped > 0) console.log(chalk8.dim(` ${skipped} agent(s) already up to date`));
2535
1534
  if (installed === 0 && skipped > 0) {
2536
- console.log(chalk9.green(" All agents are already installed. Use --force to re-install."));
1535
+ console.log(chalk8.green(" All agents are already installed. Use --force to re-install."));
2537
1536
  }
2538
1537
  console.log();
1538
+ if (!opts.global && installed > 0) await checkAndAutoRegenerate(hubDir);
2539
1539
  })
2540
1540
  );
2541
1541
 
2542
1542
  // src/commands/hooks.ts
2543
- import { Command as Command10 } from "commander";
2544
- import { existsSync as existsSync8, statSync as statSync3 } from "fs";
2545
- import { mkdir as mkdir6, readdir as readdir4, readFile as readFile7, rm as rm3, copyFile as copyFile3, cp as cp3 } from "fs/promises";
2546
- import { join as join11, resolve as resolve4 } from "path";
1543
+ import { Command as Command9 } from "commander";
1544
+ import { existsSync as existsSync7, statSync as statSync3 } from "fs";
1545
+ import { mkdir as mkdir5, readdir as readdir3, readFile as readFile5, rm as rm3, copyFile as copyFile2, cp as cp2 } from "fs/promises";
1546
+ import { join as join9, resolve as resolve3 } from "path";
2547
1547
  import { execSync as execSync6 } from "child_process";
2548
- import chalk10 from "chalk";
1548
+ import chalk9 from "chalk";
2549
1549
  var DEFAULT_REGISTRY_REPO4 = process.env.HUB_REGISTRY || "arvoreeducacao/rhm";
2550
1550
  function tmpDir3() {
2551
- return join11(process.env.TMPDIR || "/tmp", `hub-hooks-${Date.now()}`);
1551
+ return join9(process.env.TMPDIR || "/tmp", `hub-hooks-${Date.now()}`);
2552
1552
  }
2553
1553
  async function listLocalHooks(hooksDir) {
2554
1554
  const hooks = [];
2555
- if (!existsSync8(hooksDir)) return hooks;
2556
- const entries = await readdir4(hooksDir);
1555
+ if (!existsSync7(hooksDir)) return hooks;
1556
+ const entries = await readdir3(hooksDir);
2557
1557
  for (const entry of entries) {
2558
- const entryPath = join11(hooksDir, entry);
1558
+ const entryPath = join9(hooksDir, entry);
2559
1559
  const stat = statSync3(entryPath);
2560
1560
  if (stat.isFile() && entry.endsWith(".sh")) {
2561
1561
  hooks.push({ name: entry.replace(/\.sh$/, ""), description: "" });
2562
1562
  } else if (stat.isDirectory()) {
2563
- const readmePath = join11(entryPath, "README.md");
1563
+ const readmePath = join9(entryPath, "README.md");
2564
1564
  let description = "";
2565
- if (existsSync8(readmePath)) {
2566
- const content = await readFile7(readmePath, "utf-8");
1565
+ if (existsSync7(readmePath)) {
1566
+ const content = await readFile5(readmePath, "utf-8");
2567
1567
  const firstLine = content.split("\n").find((l) => l.trim() && !l.startsWith("#"));
2568
1568
  description = firstLine?.trim() || "";
2569
1569
  }
@@ -2574,84 +1574,84 @@ async function listLocalHooks(hooksDir) {
2574
1574
  }
2575
1575
  async function addFromRegistry3(hookName, hubDir, opts) {
2576
1576
  const repo = opts.repo || DEFAULT_REGISTRY_REPO4;
2577
- const targetDir = join11(hubDir, "hooks", hookName);
2578
- console.log(chalk10.cyan(` Downloading hook '${hookName}' from ${repo}...`));
1577
+ const targetDir = join9(hubDir, "hooks", hookName);
1578
+ console.log(chalk9.cyan(` Downloading hook '${hookName}' from ${repo}...`));
2579
1579
  try {
2580
1580
  await downloadDirFromGitHub(repo, `hooks/${hookName}`, targetDir);
2581
- console.log(chalk10.green(` Installed: ${hookName}`));
2582
- console.log(chalk10.dim("\n Add the hook to hub.yaml to bind it to an event. Example:"));
2583
- console.log(chalk10.dim(` hooks:`));
2584
- console.log(chalk10.dim(` after_file_edit:`));
2585
- console.log(chalk10.dim(` - type: command`));
2586
- console.log(chalk10.dim(` command: "./hooks/${hookName}/hook.sh"
1581
+ console.log(chalk9.green(` Installed: ${hookName}`));
1582
+ console.log(chalk9.dim("\n Add the hook to hub.yaml to bind it to an event. Example:"));
1583
+ console.log(chalk9.dim(` hooks:`));
1584
+ console.log(chalk9.dim(` after_file_edit:`));
1585
+ console.log(chalk9.dim(` - type: command`));
1586
+ console.log(chalk9.dim(` command: "./hooks/${hookName}/hook.sh"
2587
1587
  `));
2588
1588
  } catch {
2589
- console.log(chalk10.red(` Hook '${hookName}' not found in registry (${repo})`));
2590
- console.log(chalk10.dim(" Run 'hub registry list --type hook' to see available hooks."));
1589
+ console.log(chalk9.red(` Hook '${hookName}' not found in registry (${repo})`));
1590
+ console.log(chalk9.dim(" Run 'hub registry list --type hook' to see available hooks."));
2591
1591
  }
2592
1592
  }
2593
1593
  async function addFromLocalPath3(localPath, hubDir, opts) {
2594
- const absPath = resolve4(localPath);
2595
- if (!existsSync8(absPath)) {
2596
- console.log(chalk10.red(` Path not found: ${absPath}`));
1594
+ const absPath = resolve3(localPath);
1595
+ if (!existsSync7(absPath)) {
1596
+ console.log(chalk9.red(` Path not found: ${absPath}`));
2597
1597
  return;
2598
1598
  }
2599
1599
  const stat = statSync3(absPath);
2600
- const sourceHooksDir = stat.isDirectory() ? existsSync8(join11(absPath, "hooks")) ? join11(absPath, "hooks") : absPath : absPath;
1600
+ const sourceHooksDir = stat.isDirectory() ? existsSync7(join9(absPath, "hooks")) ? join9(absPath, "hooks") : absPath : absPath;
2601
1601
  await installHooksFromDir(sourceHooksDir, hubDir, opts);
2602
1602
  }
2603
1603
  async function installHooksFromDir(sourceDir, hubDir, opts) {
2604
- if (!existsSync8(sourceDir)) {
2605
- console.log(chalk10.red(" No hooks directory found in source"));
1604
+ if (!existsSync7(sourceDir)) {
1605
+ console.log(chalk9.red(" No hooks directory found in source"));
2606
1606
  return;
2607
1607
  }
2608
- const entries = await readdir4(sourceDir);
1608
+ const entries = await readdir3(sourceDir);
2609
1609
  const hookEntries = entries.filter((e) => {
2610
- const p = join11(sourceDir, e);
1610
+ const p = join9(sourceDir, e);
2611
1611
  return e.endsWith(".sh") || statSync3(p).isDirectory();
2612
1612
  });
2613
1613
  if (hookEntries.length === 0) {
2614
- console.log(chalk10.red(" No hook files found"));
1614
+ console.log(chalk9.red(" No hook files found"));
2615
1615
  return;
2616
1616
  }
2617
1617
  const toInstall = opts.hook ? hookEntries.filter((e) => e === opts.hook || e === `${opts.hook}.sh` || e.replace(/\.sh$/, "") === opts.hook) : hookEntries;
2618
1618
  if (opts.hook && toInstall.length === 0) {
2619
1619
  const available = hookEntries.map((e) => e.replace(/\.sh$/, "")).join(", ");
2620
- console.log(chalk10.red(` Hook '${opts.hook}' not found. Available: ${available}`));
1620
+ console.log(chalk9.red(` Hook '${opts.hook}' not found. Available: ${available}`));
2621
1621
  return;
2622
1622
  }
2623
- const targetBase = join11(hubDir, "hooks");
2624
- await mkdir6(targetBase, { recursive: true });
1623
+ const targetBase = join9(hubDir, "hooks");
1624
+ await mkdir5(targetBase, { recursive: true });
2625
1625
  for (const entry of toInstall) {
2626
- const src = join11(sourceDir, entry);
1626
+ const src = join9(sourceDir, entry);
2627
1627
  const stat = statSync3(src);
2628
1628
  if (stat.isDirectory()) {
2629
- await cp3(src, join11(targetBase, entry), { recursive: true });
1629
+ await cp2(src, join9(targetBase, entry), { recursive: true });
2630
1630
  } else {
2631
- await copyFile3(src, join11(targetBase, entry));
1631
+ await copyFile2(src, join9(targetBase, entry));
2632
1632
  }
2633
- console.log(chalk10.green(` Installed: ${entry.replace(/\.sh$/, "")}`));
1633
+ console.log(chalk9.green(` Installed: ${entry.replace(/\.sh$/, "")}`));
2634
1634
  }
2635
- console.log(chalk10.green(`
1635
+ console.log(chalk9.green(`
2636
1636
  ${toInstall.length} hook(s) installed
2637
1637
  `));
2638
1638
  }
2639
1639
  async function addFromGitRepo3(source, hubDir, opts) {
2640
1640
  const tmp = tmpDir3();
2641
1641
  try {
2642
- console.log(chalk10.cyan(` Cloning ${source}...`));
1642
+ console.log(chalk9.cyan(` Cloning ${source}...`));
2643
1643
  try {
2644
1644
  execSync6(`git clone --depth 1 ${source} ${tmp}`, {
2645
1645
  stdio: ["pipe", "pipe", "pipe"]
2646
1646
  });
2647
1647
  } catch {
2648
- console.log(chalk10.red(` Repository not found or not accessible: ${source}`));
1648
+ console.log(chalk9.red(` Repository not found or not accessible: ${source}`));
2649
1649
  return;
2650
1650
  }
2651
- const sourceHooksDir = join11(tmp, "hooks");
1651
+ const sourceHooksDir = join9(tmp, "hooks");
2652
1652
  await installHooksFromDir(sourceHooksDir, hubDir, opts);
2653
1653
  } finally {
2654
- if (existsSync8(tmp)) {
1654
+ if (existsSync7(tmp)) {
2655
1655
  await rm3(tmp, { recursive: true });
2656
1656
  }
2657
1657
  }
@@ -2662,10 +1662,10 @@ function isLocalPath3(source) {
2662
1662
  function isRepoReference2(source) {
2663
1663
  return source.startsWith("git@") || source.startsWith("https://") || source.includes("/");
2664
1664
  }
2665
- var hooksCommand = new Command10("hooks").description("Manage editor hooks").addCommand(
2666
- new Command10("add").description("Install hooks from the registry, a git repository, or local path").argument("<source>", "Hook name (from registry), GitHub shorthand (org/repo), git URL, or local path").option("--hook <name>", "Install a specific hook only (for repo sources)").option("-r, --repo <repo>", "Registry repository (owner/repo)").action(async (source, opts) => {
1665
+ var hooksCommand = new Command9("hooks").description("Manage editor hooks").addCommand(
1666
+ new Command9("add").description("Install hooks from the registry, a git repository, or local path").argument("<source>", "Hook name (from registry), GitHub shorthand (org/repo), git URL, or local path").option("--hook <name>", "Install a specific hook only (for repo sources)").option("-r, --repo <repo>", "Registry repository (owner/repo)").action(async (source, opts) => {
2667
1667
  const hubDir = process.cwd();
2668
- console.log(chalk10.blue(`
1668
+ console.log(chalk9.blue(`
2669
1669
  Installing hooks from ${source}
2670
1670
  `));
2671
1671
  if (isLocalPath3(source)) {
@@ -2680,75 +1680,78 @@ Installing hooks from ${source}
2680
1680
  } else {
2681
1681
  await addFromRegistry3(source, hubDir, opts);
2682
1682
  }
1683
+ await checkAndAutoRegenerate(hubDir);
2683
1684
  })
2684
1685
  ).addCommand(
2685
- new Command10("list").description("List installed hooks").action(async () => {
1686
+ new Command9("list").description("List installed hooks").action(async () => {
2686
1687
  const hubDir = process.cwd();
2687
- const hooksDir = join11(hubDir, "hooks");
2688
- console.log(chalk10.blue("\nInstalled hooks\n"));
1688
+ const hooksDir = join9(hubDir, "hooks");
1689
+ console.log(chalk9.blue("\nInstalled hooks\n"));
2689
1690
  const hooks = await listLocalHooks(hooksDir);
2690
1691
  if (hooks.length > 0) {
2691
1692
  for (const h of hooks) {
2692
- console.log(` ${chalk10.yellow(h.name)}${h.description ? ` \u2014 ${h.description}` : ""}`);
1693
+ console.log(` ${chalk9.yellow(h.name)}${h.description ? ` \u2014 ${h.description}` : ""}`);
2693
1694
  }
2694
1695
  } else {
2695
- console.log(chalk10.dim(" No hooks installed (hooks/)"));
1696
+ console.log(chalk9.dim(" No hooks installed (hooks/)"));
2696
1697
  }
2697
1698
  console.log();
2698
1699
  })
2699
1700
  ).addCommand(
2700
- new Command10("find").description("Browse curated hooks in the Repo Hub directory").argument("[query]", "Search term").action(async (query) => {
2701
- const base = "https://rhm-website.vercel.app/directory?type=hook";
1701
+ new Command9("find").description("Browse curated hooks in the Repo Hub directory").argument("[query]", "Search term").action(async (query) => {
1702
+ const base = "https://hub.arvore.com.br/directory?type=hook";
2702
1703
  const url = query ? `${base}&q=${encodeURIComponent(query)}` : base;
2703
- console.log(chalk10.blue("\n Browse curated hooks at:\n"));
2704
- console.log(chalk10.cyan(` ${url}
1704
+ console.log(chalk9.blue("\n Browse curated hooks at:\n"));
1705
+ console.log(chalk9.cyan(` ${url}
2705
1706
  `));
2706
- console.log(chalk10.dim(" Install with: hub hooks add <owner>/<repo>"));
2707
- console.log(chalk10.dim(" Example: hub hooks add obra/superpowers\n"));
1707
+ console.log(chalk9.dim(" Install with: hub hooks add <owner>/<repo>"));
1708
+ console.log(chalk9.dim(" Example: hub hooks add obra/superpowers\n"));
2708
1709
  })
2709
1710
  ).addCommand(
2710
- new Command10("remove").description("Remove a hook").argument("<name>", "Hook name to remove").action(async (name) => {
1711
+ new Command9("remove").description("Remove a hook").argument("<name>", "Hook name to remove").action(async (name) => {
2711
1712
  const hubDir = process.cwd();
2712
- const hooksDir = join11(hubDir, "hooks");
2713
- const shFile = join11(hooksDir, `${name}.sh`);
2714
- const dirPath = join11(hooksDir, name);
2715
- if (existsSync8(dirPath) && statSync3(dirPath).isDirectory()) {
1713
+ const hooksDir = join9(hubDir, "hooks");
1714
+ const shFile = join9(hooksDir, `${name}.sh`);
1715
+ const dirPath = join9(hooksDir, name);
1716
+ if (existsSync7(dirPath) && statSync3(dirPath).isDirectory()) {
2716
1717
  await rm3(dirPath, { recursive: true });
2717
- console.log(chalk10.green(`
1718
+ console.log(chalk9.green(`
2718
1719
  Removed hook: ${name}
2719
1720
  `));
2720
- } else if (existsSync8(shFile)) {
1721
+ } else if (existsSync7(shFile)) {
2721
1722
  await rm3(shFile);
2722
- console.log(chalk10.green(`
1723
+ console.log(chalk9.green(`
2723
1724
  Removed hook: ${name}
2724
1725
  `));
2725
1726
  } else {
2726
- console.log(chalk10.red(`
1727
+ console.log(chalk9.red(`
2727
1728
  Hook '${name}' not found in hooks/
2728
1729
  `));
1730
+ return;
2729
1731
  }
1732
+ await checkAndAutoRegenerate(hubDir);
2730
1733
  })
2731
1734
  );
2732
1735
 
2733
1736
  // src/commands/commands.ts
2734
- import { Command as Command11 } from "commander";
2735
- import { existsSync as existsSync9, statSync as statSync4 } from "fs";
2736
- import { mkdir as mkdir7, readdir as readdir5, readFile as readFile8, rm as rm4, copyFile as copyFile4, writeFile as writeFile9 } from "fs/promises";
2737
- import { join as join12, resolve as resolve5 } from "path";
1737
+ import { Command as Command10 } from "commander";
1738
+ import { existsSync as existsSync8, statSync as statSync4 } from "fs";
1739
+ import { mkdir as mkdir6, readdir as readdir4, readFile as readFile6, rm as rm4, copyFile as copyFile3, writeFile as writeFile8 } from "fs/promises";
1740
+ import { join as join10, resolve as resolve4 } from "path";
2738
1741
  import { execSync as execSync7 } from "child_process";
2739
- import chalk11 from "chalk";
1742
+ import chalk10 from "chalk";
2740
1743
  var DEFAULT_REGISTRY_REPO5 = process.env.HUB_REGISTRY || "arvoreeducacao/rhm";
2741
1744
  var DEFAULT_BRANCH3 = "main";
2742
1745
  function tmpDir4() {
2743
- return join12(process.env.TMPDIR || "/tmp", `hub-commands-${Date.now()}`);
1746
+ return join10(process.env.TMPDIR || "/tmp", `hub-commands-${Date.now()}`);
2744
1747
  }
2745
1748
  async function listLocalCommands(commandsDir) {
2746
1749
  const commands = [];
2747
- if (!existsSync9(commandsDir)) return commands;
2748
- const files = await readdir5(commandsDir);
1750
+ if (!existsSync8(commandsDir)) return commands;
1751
+ const files = await readdir4(commandsDir);
2749
1752
  for (const file of files) {
2750
1753
  if (!file.endsWith(".md")) continue;
2751
- const content = await readFile8(join12(commandsDir, file), "utf-8");
1754
+ const content = await readFile6(join10(commandsDir, file), "utf-8");
2752
1755
  const firstLine = content.split("\n").find((l) => l.trim() && !l.startsWith("#"));
2753
1756
  commands.push({
2754
1757
  name: file.replace(/\.md$/, ""),
@@ -2761,91 +1764,91 @@ async function addFromRegistry4(commandName, hubDir, opts) {
2761
1764
  const repo = opts.repo || DEFAULT_REGISTRY_REPO5;
2762
1765
  const fileName = commandName.endsWith(".md") ? commandName : `${commandName}.md`;
2763
1766
  const rawUrl = `https://raw.githubusercontent.com/${repo}/${DEFAULT_BRANCH3}/commands/${fileName}`;
2764
- console.log(chalk11.cyan(` Downloading command '${commandName}' from ${repo}...`));
1767
+ console.log(chalk10.cyan(` Downloading command '${commandName}' from ${repo}...`));
2765
1768
  try {
2766
1769
  const res = await fetch(rawUrl);
2767
1770
  if (!res.ok) {
2768
- console.log(chalk11.red(` Command '${commandName}' not found in registry (${repo})`));
2769
- console.log(chalk11.dim(" Run 'hub registry list --type command' to see available commands."));
1771
+ console.log(chalk10.red(` Command '${commandName}' not found in registry (${repo})`));
1772
+ console.log(chalk10.dim(" Run 'hub registry list --type command' to see available commands."));
2770
1773
  return;
2771
1774
  }
2772
1775
  const content = await res.text();
2773
- const targetDir = join12(hubDir, "commands");
2774
- await mkdir7(targetDir, { recursive: true });
2775
- await writeFile9(join12(targetDir, fileName), content, "utf-8");
2776
- console.log(chalk11.green(` Installed: ${commandName}`));
2777
- console.log(chalk11.dim(`
1776
+ const targetDir = join10(hubDir, "commands");
1777
+ await mkdir6(targetDir, { recursive: true });
1778
+ await writeFile8(join10(targetDir, fileName), content, "utf-8");
1779
+ console.log(chalk10.green(` Installed: ${commandName}`));
1780
+ console.log(chalk10.dim(`
2778
1781
  Use it in Cursor with /${commandName}`));
2779
- console.log(chalk11.dim(` Make sure hub.yaml has: commands_dir: ./commands
1782
+ console.log(chalk10.dim(` Make sure hub.yaml has: commands_dir: ./commands
2780
1783
  `));
2781
1784
  } catch (err) {
2782
- console.log(chalk11.red(` Failed to download command '${commandName}': ${err.message}`));
1785
+ console.log(chalk10.red(` Failed to download command '${commandName}': ${err.message}`));
2783
1786
  }
2784
1787
  }
2785
1788
  async function addFromLocalPath4(localPath, hubDir, opts) {
2786
- const absPath = resolve5(localPath);
2787
- if (!existsSync9(absPath)) {
2788
- console.log(chalk11.red(` Path not found: ${absPath}`));
1789
+ const absPath = resolve4(localPath);
1790
+ if (!existsSync8(absPath)) {
1791
+ console.log(chalk10.red(` Path not found: ${absPath}`));
2789
1792
  return;
2790
1793
  }
2791
1794
  const stat = statSync4(absPath);
2792
1795
  if (stat.isFile() && absPath.endsWith(".md")) {
2793
- const targetDir = join12(hubDir, "commands");
2794
- await mkdir7(targetDir, { recursive: true });
1796
+ const targetDir = join10(hubDir, "commands");
1797
+ await mkdir6(targetDir, { recursive: true });
2795
1798
  const fileName = absPath.split("/").pop();
2796
- await copyFile4(absPath, join12(targetDir, fileName));
2797
- console.log(chalk11.green(` Installed: ${fileName.replace(/\.md$/, "")}`));
2798
- console.log(chalk11.green(`
1799
+ await copyFile3(absPath, join10(targetDir, fileName));
1800
+ console.log(chalk10.green(` Installed: ${fileName.replace(/\.md$/, "")}`));
1801
+ console.log(chalk10.green(`
2799
1802
  1 command(s) installed
2800
1803
  `));
2801
1804
  return;
2802
1805
  }
2803
- const sourceDir = stat.isDirectory() ? existsSync9(join12(absPath, "commands")) ? join12(absPath, "commands") : absPath : absPath;
1806
+ const sourceDir = stat.isDirectory() ? existsSync8(join10(absPath, "commands")) ? join10(absPath, "commands") : absPath : absPath;
2804
1807
  await installCommandsFromDir(sourceDir, hubDir, opts);
2805
1808
  }
2806
1809
  async function installCommandsFromDir(sourceDir, hubDir, opts) {
2807
- if (!existsSync9(sourceDir)) {
2808
- console.log(chalk11.red(" No commands directory found in source"));
1810
+ if (!existsSync8(sourceDir)) {
1811
+ console.log(chalk10.red(" No commands directory found in source"));
2809
1812
  return;
2810
1813
  }
2811
- const files = await readdir5(sourceDir);
1814
+ const files = await readdir4(sourceDir);
2812
1815
  const mdFiles = files.filter((f) => f.endsWith(".md"));
2813
1816
  if (mdFiles.length === 0) {
2814
- console.log(chalk11.red(" No command files found (looking for *.md)"));
1817
+ console.log(chalk10.red(" No command files found (looking for *.md)"));
2815
1818
  return;
2816
1819
  }
2817
1820
  const toInstall = opts.command ? mdFiles.filter((f) => f === `${opts.command}.md` || f === opts.command) : mdFiles;
2818
1821
  if (opts.command && toInstall.length === 0) {
2819
1822
  const available = mdFiles.map((f) => f.replace(/\.md$/, "")).join(", ");
2820
- console.log(chalk11.red(` Command '${opts.command}' not found. Available: ${available}`));
1823
+ console.log(chalk10.red(` Command '${opts.command}' not found. Available: ${available}`));
2821
1824
  return;
2822
1825
  }
2823
- const targetDir = join12(hubDir, "commands");
2824
- await mkdir7(targetDir, { recursive: true });
1826
+ const targetDir = join10(hubDir, "commands");
1827
+ await mkdir6(targetDir, { recursive: true });
2825
1828
  for (const file of toInstall) {
2826
- await copyFile4(join12(sourceDir, file), join12(targetDir, file));
2827
- console.log(chalk11.green(` Installed: ${file.replace(/\.md$/, "")}`));
1829
+ await copyFile3(join10(sourceDir, file), join10(targetDir, file));
1830
+ console.log(chalk10.green(` Installed: ${file.replace(/\.md$/, "")}`));
2828
1831
  }
2829
- console.log(chalk11.green(`
1832
+ console.log(chalk10.green(`
2830
1833
  ${toInstall.length} command(s) installed
2831
1834
  `));
2832
1835
  }
2833
1836
  async function addFromGitRepo4(source, hubDir, opts) {
2834
1837
  const tmp = tmpDir4();
2835
1838
  try {
2836
- console.log(chalk11.cyan(` Cloning ${source}...`));
1839
+ console.log(chalk10.cyan(` Cloning ${source}...`));
2837
1840
  try {
2838
1841
  execSync7(`git clone --depth 1 ${source} ${tmp}`, {
2839
1842
  stdio: ["pipe", "pipe", "pipe"]
2840
1843
  });
2841
1844
  } catch {
2842
- console.log(chalk11.red(` Repository not found or not accessible: ${source}`));
1845
+ console.log(chalk10.red(` Repository not found or not accessible: ${source}`));
2843
1846
  return;
2844
1847
  }
2845
- const sourceCommandsDir = join12(tmp, "commands");
1848
+ const sourceCommandsDir = join10(tmp, "commands");
2846
1849
  await installCommandsFromDir(sourceCommandsDir, hubDir, opts);
2847
1850
  } finally {
2848
- if (existsSync9(tmp)) {
1851
+ if (existsSync8(tmp)) {
2849
1852
  await rm4(tmp, { recursive: true });
2850
1853
  }
2851
1854
  }
@@ -2856,10 +1859,10 @@ function isLocalPath4(source) {
2856
1859
  function isRepoReference3(source) {
2857
1860
  return source.startsWith("git@") || source.startsWith("https://") || source.includes("/");
2858
1861
  }
2859
- var commandsCommand = new Command11("commands").description("Manage slash commands (Cursor)").addCommand(
2860
- new Command11("add").description("Install commands from the registry, a git repository, or local path").argument("<source>", "Command name (from registry), GitHub shorthand (org/repo), git URL, or local path").option("-c, --command <name>", "Install a specific command only (for repo sources)").option("-r, --repo <repo>", "Registry repository (owner/repo)").action(async (source, opts) => {
1862
+ var commandsCommand = new Command10("commands").description("Manage slash commands (Cursor)").addCommand(
1863
+ new Command10("add").description("Install commands from the registry, a git repository, or local path").argument("<source>", "Command name (from registry), GitHub shorthand (org/repo), git URL, or local path").option("-c, --command <name>", "Install a specific command only (for repo sources)").option("-r, --repo <repo>", "Registry repository (owner/repo)").action(async (source, opts) => {
2861
1864
  const hubDir = process.cwd();
2862
- console.log(chalk11.blue(`
1865
+ console.log(chalk10.blue(`
2863
1866
  Installing commands from ${source}
2864
1867
  `));
2865
1868
  if (isLocalPath4(source)) {
@@ -2874,88 +1877,90 @@ Installing commands from ${source}
2874
1877
  } else {
2875
1878
  await addFromRegistry4(source, hubDir, opts);
2876
1879
  }
1880
+ await checkAndAutoRegenerate(hubDir);
2877
1881
  })
2878
1882
  ).addCommand(
2879
- new Command11("list").description("List installed commands").action(async () => {
1883
+ new Command10("list").description("List installed commands").action(async () => {
2880
1884
  const hubDir = process.cwd();
2881
- const commandsDir = join12(hubDir, "commands");
2882
- console.log(chalk11.blue("\nInstalled commands\n"));
1885
+ const commandsDir = join10(hubDir, "commands");
1886
+ console.log(chalk10.blue("\nInstalled commands\n"));
2883
1887
  const commands = await listLocalCommands(commandsDir);
2884
1888
  if (commands.length > 0) {
2885
1889
  for (const c of commands) {
2886
- console.log(` ${chalk11.yellow(`/${c.name}`)}${c.description ? ` \u2014 ${c.description}` : ""}`);
1890
+ console.log(` ${chalk10.yellow(`/${c.name}`)}${c.description ? ` \u2014 ${c.description}` : ""}`);
2887
1891
  }
2888
1892
  } else {
2889
- console.log(chalk11.dim(" No commands installed (commands/)"));
1893
+ console.log(chalk10.dim(" No commands installed (commands/)"));
2890
1894
  }
2891
1895
  console.log();
2892
1896
  })
2893
1897
  ).addCommand(
2894
- new Command11("find").description("Browse curated commands in the Repo Hub directory").argument("[query]", "Search term").action(async (query) => {
2895
- const base = "https://rhm-website.vercel.app/directory?type=command";
1898
+ new Command10("find").description("Browse curated commands in the Repo Hub directory").argument("[query]", "Search term").action(async (query) => {
1899
+ const base = "https://hub.arvore.com.br/directory?type=command";
2896
1900
  const url = query ? `${base}&q=${encodeURIComponent(query)}` : base;
2897
- console.log(chalk11.blue("\n Browse curated commands at:\n"));
2898
- console.log(chalk11.cyan(` ${url}
1901
+ console.log(chalk10.blue("\n Browse curated commands at:\n"));
1902
+ console.log(chalk10.cyan(` ${url}
2899
1903
  `));
2900
- console.log(chalk11.dim(" Install with: hub commands add <owner>/<repo>"));
2901
- console.log(chalk11.dim(" Example: hub commands add obra/superpowers\n"));
1904
+ console.log(chalk10.dim(" Install with: hub commands add <owner>/<repo>"));
1905
+ console.log(chalk10.dim(" Example: hub commands add obra/superpowers\n"));
2902
1906
  })
2903
1907
  ).addCommand(
2904
- new Command11("remove").description("Remove a command").argument("<name>", "Command name to remove").action(async (name) => {
1908
+ new Command10("remove").description("Remove a command").argument("<name>", "Command name to remove").action(async (name) => {
2905
1909
  const hubDir = process.cwd();
2906
- const commandsDir = join12(hubDir, "commands");
1910
+ const commandsDir = join10(hubDir, "commands");
2907
1911
  const fileName = name.endsWith(".md") ? name : `${name}.md`;
2908
- const target = join12(commandsDir, fileName);
2909
- if (!existsSync9(target)) {
2910
- console.log(chalk11.red(`
1912
+ const target = join10(commandsDir, fileName);
1913
+ if (!existsSync8(target)) {
1914
+ console.log(chalk10.red(`
2911
1915
  Command '${name}' not found in commands/
2912
1916
  `));
2913
1917
  return;
2914
1918
  }
2915
1919
  await rm4(target);
2916
- console.log(chalk11.green(`
1920
+ console.log(chalk10.green(`
2917
1921
  Removed command: ${name}
2918
1922
  `));
1923
+ await checkAndAutoRegenerate(hubDir);
2919
1924
  })
2920
1925
  );
2921
1926
 
2922
1927
  // src/commands/repos.ts
2923
- import { Command as Command12 } from "commander";
2924
- import { existsSync as existsSync10 } from "fs";
2925
- import { join as join13 } from "path";
1928
+ import { Command as Command11 } from "commander";
1929
+ import { existsSync as existsSync9 } from "fs";
1930
+ import { join as join11 } from "path";
2926
1931
  import { execSync as execSync8 } from "child_process";
2927
- import chalk12 from "chalk";
2928
- var pullCommand = new Command12("pull").description("Pull latest changes in all repositories").action(async () => {
1932
+ import chalk11 from "chalk";
1933
+ var pullCommand = new Command11("pull").description("Pull latest changes in all repositories").action(async () => {
2929
1934
  const hubDir = process.cwd();
2930
1935
  const config = await loadHubConfig(hubDir);
2931
- console.log(chalk12.blue("\n\u2501\u2501\u2501 Pulling latest changes \u2501\u2501\u2501\n"));
1936
+ console.log(chalk11.blue("\n\u2501\u2501\u2501 Pulling latest changes \u2501\u2501\u2501\n"));
2932
1937
  for (const repo of config.repos) {
2933
- const fullPath = join13(hubDir, repo.path);
2934
- if (!existsSync10(fullPath)) {
2935
- console.log(chalk12.red(` ${repo.name}: not cloned`));
1938
+ const fullPath = join11(hubDir, repo.path);
1939
+ if (!existsSync9(fullPath)) {
1940
+ console.log(chalk11.red(` ${repo.name}: not cloned`));
2936
1941
  continue;
2937
1942
  }
2938
- console.log(chalk12.yellow(`\u25B8 ${repo.name}`));
1943
+ console.log(chalk11.yellow(`\u25B8 ${repo.name}`));
2939
1944
  try {
2940
1945
  execSync8("git pull --rebase", { cwd: fullPath, stdio: "inherit" });
2941
- console.log(chalk12.green(" Updated"));
1946
+ console.log(chalk11.green(" Updated"));
2942
1947
  } catch {
2943
- console.log(chalk12.red(" Failed to pull"));
1948
+ console.log(chalk11.red(" Failed to pull"));
2944
1949
  }
2945
1950
  }
2946
1951
  console.log();
2947
1952
  });
2948
- var statusCommand = new Command12("status").description("Show git status for all repositories").action(async () => {
1953
+ var statusCommand = new Command11("status").description("Show git status for all repositories").action(async () => {
2949
1954
  const hubDir = process.cwd();
2950
1955
  const config = await loadHubConfig(hubDir);
2951
- console.log(chalk12.blue("\n\u2501\u2501\u2501 Git status \u2501\u2501\u2501\n"));
1956
+ console.log(chalk11.blue("\n\u2501\u2501\u2501 Git status \u2501\u2501\u2501\n"));
2952
1957
  for (const repo of config.repos) {
2953
- const fullPath = join13(hubDir, repo.path);
2954
- if (!existsSync10(fullPath)) {
2955
- console.log(chalk12.red(` ${repo.name}: not cloned`));
1958
+ const fullPath = join11(hubDir, repo.path);
1959
+ if (!existsSync9(fullPath)) {
1960
+ console.log(chalk11.red(` ${repo.name}: not cloned`));
2956
1961
  continue;
2957
1962
  }
2958
- console.log(chalk12.yellow(`\u25B8 ${repo.name}`));
1963
+ console.log(chalk11.yellow(`\u25B8 ${repo.name}`));
2959
1964
  try {
2960
1965
  const branch = execSync8("git branch --show-current", {
2961
1966
  cwd: fullPath,
@@ -2986,43 +1991,43 @@ var statusCommand = new Command12("status").description("Show git status for all
2986
1991
  console.log(` Changes: ${changes} file(s)`);
2987
1992
  console.log(` Ahead: ${ahead} | Behind: ${behind}`);
2988
1993
  } catch {
2989
- console.log(chalk12.red(" Failed to get status"));
1994
+ console.log(chalk11.red(" Failed to get status"));
2990
1995
  }
2991
1996
  console.log();
2992
1997
  }
2993
1998
  });
2994
- var execCommand = new Command12("exec").description("Execute a command in all repositories").argument("<cmd...>", "Command to execute").passThroughOptions().allowUnknownOption().action(async (cmd) => {
1999
+ var execCommand = new Command11("exec").description("Execute a command in all repositories").argument("<cmd...>", "Command to execute").passThroughOptions().allowUnknownOption().action(async (cmd) => {
2995
2000
  const hubDir = process.cwd();
2996
2001
  const config = await loadHubConfig(hubDir);
2997
2002
  const command = cmd.join(" ");
2998
- console.log(chalk12.blue(`
2003
+ console.log(chalk11.blue(`
2999
2004
  \u2501\u2501\u2501 Executing: ${command} \u2501\u2501\u2501
3000
2005
  `));
3001
2006
  for (const repo of config.repos) {
3002
- const fullPath = join13(hubDir, repo.path);
3003
- if (!existsSync10(fullPath)) {
3004
- console.log(chalk12.red(` ${repo.name}: not cloned`));
2007
+ const fullPath = join11(hubDir, repo.path);
2008
+ if (!existsSync9(fullPath)) {
2009
+ console.log(chalk11.red(` ${repo.name}: not cloned`));
3005
2010
  continue;
3006
2011
  }
3007
- console.log(chalk12.yellow(`\u25B8 ${repo.name}`));
2012
+ console.log(chalk11.yellow(`\u25B8 ${repo.name}`));
3008
2013
  try {
3009
2014
  execSync8(command, { cwd: fullPath, stdio: "inherit" });
3010
2015
  } catch {
3011
- console.log(chalk12.red(` Command failed in ${repo.name}`));
2016
+ console.log(chalk11.red(` Command failed in ${repo.name}`));
3012
2017
  }
3013
2018
  }
3014
2019
  console.log();
3015
2020
  });
3016
2021
 
3017
2022
  // src/commands/worktree.ts
3018
- import { Command as Command13 } from "commander";
3019
- import { existsSync as existsSync11 } from "fs";
3020
- import { cp as cp4, mkdir as mkdir8 } from "fs/promises";
3021
- import { join as join14 } from "path";
2023
+ import { Command as Command12 } from "commander";
2024
+ import { existsSync as existsSync10 } from "fs";
2025
+ import { cp as cp3, mkdir as mkdir7 } from "fs/promises";
2026
+ import { join as join12 } from "path";
3022
2027
  import { execSync as execSync9 } from "child_process";
3023
- import chalk13 from "chalk";
2028
+ import chalk12 from "chalk";
3024
2029
  function getWorktreeBase() {
3025
- return join14(process.env.HOME || "~", ".cursor", "worktrees", "repo-hub");
2030
+ return join12(process.env.HOME || "~", ".cursor", "worktrees", "repo-hub");
3026
2031
  }
3027
2032
  function isGitRepo(dir) {
3028
2033
  try {
@@ -3035,74 +2040,74 @@ function isGitRepo(dir) {
3035
2040
  return false;
3036
2041
  }
3037
2042
  }
3038
- var worktreeCommand = new Command13("worktree").description("Manage git worktrees for parallel work").addCommand(
3039
- new Command13("add").description("Create a new worktree with environment files copied").argument("<name>", "Worktree name").action(async (name) => {
2043
+ var worktreeCommand = new Command12("worktree").description("Manage git worktrees for parallel work").addCommand(
2044
+ new Command12("add").description("Create a new worktree with environment files copied").argument("<name>", "Worktree name").action(async (name) => {
3040
2045
  const hubDir = process.cwd();
3041
2046
  if (!isGitRepo(hubDir)) {
3042
- console.log(chalk13.red("\nThis directory is not a git repository."));
3043
- console.log(chalk13.dim("Run 'git init' first or use worktrees from a repo directory.\n"));
2047
+ console.log(chalk12.red("\nThis directory is not a git repository."));
2048
+ console.log(chalk12.dim("Run 'git init' first or use worktrees from a repo directory.\n"));
3044
2049
  return;
3045
2050
  }
3046
2051
  const config = await loadHubConfig(hubDir);
3047
2052
  const worktreeBase = getWorktreeBase();
3048
- const worktreePath = join14(worktreeBase, name);
3049
- console.log(chalk13.blue(`
2053
+ const worktreePath = join12(worktreeBase, name);
2054
+ console.log(chalk12.blue(`
3050
2055
  \u2501\u2501\u2501 Creating worktree: ${name} \u2501\u2501\u2501
3051
2056
  `));
3052
- await mkdir8(worktreeBase, { recursive: true });
3053
- console.log(chalk13.cyan(" Creating git worktree..."));
2057
+ await mkdir7(worktreeBase, { recursive: true });
2058
+ console.log(chalk12.cyan(" Creating git worktree..."));
3054
2059
  try {
3055
2060
  execSync9(`git worktree add "${worktreePath}" --detach`, {
3056
2061
  cwd: hubDir,
3057
2062
  stdio: "inherit"
3058
2063
  });
3059
2064
  } catch {
3060
- console.log(chalk13.red(" Failed to create worktree. Make sure you have commits in this repo.\n"));
2065
+ console.log(chalk12.red(" Failed to create worktree. Make sure you have commits in this repo.\n"));
3061
2066
  return;
3062
2067
  }
3063
- console.log(chalk13.cyan(" Copying environment files..."));
2068
+ console.log(chalk12.cyan(" Copying environment files..."));
3064
2069
  for (const repo of config.repos) {
3065
2070
  if (!repo.env_file) continue;
3066
- const srcEnv = join14(hubDir, repo.path, repo.env_file);
3067
- if (!existsSync11(srcEnv)) continue;
3068
- const destDir = join14(worktreePath, repo.path);
3069
- if (existsSync11(destDir)) {
3070
- const destEnv = join14(destDir, repo.env_file);
2071
+ const srcEnv = join12(hubDir, repo.path, repo.env_file);
2072
+ if (!existsSync10(srcEnv)) continue;
2073
+ const destDir = join12(worktreePath, repo.path);
2074
+ if (existsSync10(destDir)) {
2075
+ const destEnv = join12(destDir, repo.env_file);
3071
2076
  try {
3072
- await cp4(srcEnv, destEnv);
3073
- console.log(chalk13.green(` ${repo.name}: Copied ${repo.env_file}`));
2077
+ await cp3(srcEnv, destEnv);
2078
+ console.log(chalk12.green(` ${repo.name}: Copied ${repo.env_file}`));
3074
2079
  } catch {
3075
- console.log(chalk13.dim(` ${repo.name}: Could not copy env file`));
2080
+ console.log(chalk12.dim(` ${repo.name}: Could not copy env file`));
3076
2081
  }
3077
2082
  }
3078
2083
  }
3079
- console.log(chalk13.green(`
2084
+ console.log(chalk12.green(`
3080
2085
  Worktree created at: ${worktreePath}`));
3081
- console.log(chalk13.cyan(`Open in Cursor: cursor ${worktreePath}
2086
+ console.log(chalk12.cyan(`Open in Cursor: cursor ${worktreePath}
3082
2087
  `));
3083
2088
  })
3084
2089
  ).addCommand(
3085
- new Command13("list").description("List all worktrees").action(async () => {
2090
+ new Command12("list").description("List all worktrees").action(async () => {
3086
2091
  const hubDir = process.cwd();
3087
2092
  if (!isGitRepo(hubDir)) {
3088
- console.log(chalk13.red("\nThis directory is not a git repository."));
3089
- console.log(chalk13.dim("Worktrees require a git repository.\n"));
2093
+ console.log(chalk12.red("\nThis directory is not a git repository."));
2094
+ console.log(chalk12.dim("Worktrees require a git repository.\n"));
3090
2095
  return;
3091
2096
  }
3092
- console.log(chalk13.blue("\n\u2501\u2501\u2501 Git Worktrees \u2501\u2501\u2501\n"));
2097
+ console.log(chalk12.blue("\n\u2501\u2501\u2501 Git Worktrees \u2501\u2501\u2501\n"));
3093
2098
  execSync9("git worktree list", { cwd: hubDir, stdio: "inherit" });
3094
2099
  console.log();
3095
2100
  })
3096
2101
  ).addCommand(
3097
- new Command13("remove").description("Remove a worktree").argument("<name>", "Worktree name").action(async (name) => {
2102
+ new Command12("remove").description("Remove a worktree").argument("<name>", "Worktree name").action(async (name) => {
3098
2103
  const hubDir = process.cwd();
3099
2104
  if (!isGitRepo(hubDir)) {
3100
- console.log(chalk13.red("\nThis directory is not a git repository."));
3101
- console.log(chalk13.dim("Worktrees require a git repository.\n"));
2105
+ console.log(chalk12.red("\nThis directory is not a git repository."));
2106
+ console.log(chalk12.dim("Worktrees require a git repository.\n"));
3102
2107
  return;
3103
2108
  }
3104
- const worktreePath = join14(getWorktreeBase(), name);
3105
- console.log(chalk13.blue(`
2109
+ const worktreePath = join12(getWorktreeBase(), name);
2110
+ console.log(chalk12.blue(`
3106
2111
  \u2501\u2501\u2501 Removing worktree: ${name} \u2501\u2501\u2501
3107
2112
  `));
3108
2113
  try {
@@ -3110,39 +2115,39 @@ Worktree created at: ${worktreePath}`));
3110
2115
  cwd: hubDir,
3111
2116
  stdio: "inherit"
3112
2117
  });
3113
- console.log(chalk13.green(" Worktree removed\n"));
2118
+ console.log(chalk12.green(" Worktree removed\n"));
3114
2119
  } catch {
3115
- console.log(chalk13.red(` Failed to remove worktree '${name}'.
2120
+ console.log(chalk12.red(` Failed to remove worktree '${name}'.
3116
2121
  `));
3117
2122
  }
3118
2123
  })
3119
2124
  ).addCommand(
3120
- new Command13("copy-envs").description("Copy environment files to a worktree").argument("[name]", "Worktree name (copies to that worktree)").action(async (name) => {
2125
+ new Command12("copy-envs").description("Copy environment files to a worktree").argument("[name]", "Worktree name (copies to that worktree)").action(async (name) => {
3121
2126
  const hubDir = process.cwd();
3122
2127
  const config = await loadHubConfig(hubDir);
3123
- const targetDir = name ? join14(getWorktreeBase(), name) : hubDir;
3124
- if (!existsSync11(targetDir)) {
3125
- console.log(chalk13.red(`
2128
+ const targetDir = name ? join12(getWorktreeBase(), name) : hubDir;
2129
+ if (!existsSync10(targetDir)) {
2130
+ console.log(chalk12.red(`
3126
2131
  Worktree '${name}' not found at ${targetDir}
3127
2132
  `));
3128
2133
  return;
3129
2134
  }
3130
- console.log(chalk13.blue("\n\u2501\u2501\u2501 Copying environment files \u2501\u2501\u2501\n"));
3131
- console.log(chalk13.cyan(` Source: ${hubDir}`));
3132
- console.log(chalk13.cyan(` Target: ${targetDir}
2135
+ console.log(chalk12.blue("\n\u2501\u2501\u2501 Copying environment files \u2501\u2501\u2501\n"));
2136
+ console.log(chalk12.cyan(` Source: ${hubDir}`));
2137
+ console.log(chalk12.cyan(` Target: ${targetDir}
3133
2138
  `));
3134
2139
  for (const repo of config.repos) {
3135
2140
  if (!repo.env_file) continue;
3136
- const srcEnv = join14(hubDir, repo.path, repo.env_file);
3137
- if (!existsSync11(srcEnv)) continue;
3138
- const destDir = join14(targetDir, repo.path);
3139
- if (!existsSync11(destDir)) continue;
3140
- const destEnv = join14(destDir, repo.env_file);
2141
+ const srcEnv = join12(hubDir, repo.path, repo.env_file);
2142
+ if (!existsSync10(srcEnv)) continue;
2143
+ const destDir = join12(targetDir, repo.path);
2144
+ if (!existsSync10(destDir)) continue;
2145
+ const destEnv = join12(destDir, repo.env_file);
3141
2146
  try {
3142
- await cp4(srcEnv, destEnv);
3143
- console.log(chalk13.green(` ${repo.name}: Copied ${repo.env_file}`));
2147
+ await cp3(srcEnv, destEnv);
2148
+ console.log(chalk12.green(` ${repo.name}: Copied ${repo.env_file}`));
3144
2149
  } catch {
3145
- console.log(chalk13.red(` ${repo.name}: Failed to copy`));
2150
+ console.log(chalk12.red(` ${repo.name}: Failed to copy`));
3146
2151
  }
3147
2152
  }
3148
2153
  console.log();
@@ -3150,11 +2155,11 @@ Worktree '${name}' not found at ${targetDir}
3150
2155
  );
3151
2156
 
3152
2157
  // src/commands/doctor.ts
3153
- import { Command as Command14 } from "commander";
3154
- import { existsSync as existsSync12 } from "fs";
3155
- import { join as join15 } from "path";
2158
+ import { Command as Command13 } from "commander";
2159
+ import { existsSync as existsSync11 } from "fs";
2160
+ import { join as join13 } from "path";
3156
2161
  import { execSync as execSync10 } from "child_process";
3157
- import chalk14 from "chalk";
2162
+ import chalk13 from "chalk";
3158
2163
  var CHECKS = [
3159
2164
  { name: "git", command: "git", versionFlag: "--version", required: true },
3160
2165
  { name: "docker", command: "docker", versionFlag: "--version", required: true },
@@ -3209,7 +2214,7 @@ function versionMatches(actual, expected) {
3209
2214
  const actualClean = extractVersion2(actual);
3210
2215
  return actualClean.startsWith(expected) || expected.startsWith(actualClean);
3211
2216
  }
3212
- var doctorCommand = new Command14("doctor").description("Check required dependencies and tool versions from hub.yaml").action(async () => {
2217
+ var doctorCommand = new Command13("doctor").description("Check required dependencies and tool versions from hub.yaml").action(async () => {
3213
2218
  const hubDir = process.cwd();
3214
2219
  let config;
3215
2220
  try {
@@ -3217,42 +2222,42 @@ var doctorCommand = new Command14("doctor").description("Check required dependen
3217
2222
  } catch {
3218
2223
  config = null;
3219
2224
  }
3220
- console.log(chalk14.blue("\nChecking dependencies\n"));
2225
+ console.log(chalk13.blue("\nChecking dependencies\n"));
3221
2226
  let allOk = true;
3222
2227
  const required = CHECKS.filter((c) => c.required);
3223
2228
  const recommended = CHECKS.filter((c) => !c.required);
3224
- console.log(chalk14.cyan("Required:"));
2229
+ console.log(chalk13.cyan("Required:"));
3225
2230
  for (const check of required) {
3226
2231
  const result = checkCommand(check);
3227
2232
  if (result.found) {
3228
- console.log(chalk14.green(` \u2713 ${check.name}: ${result.version}`));
2233
+ console.log(chalk13.green(` \u2713 ${check.name}: ${result.version}`));
3229
2234
  } else {
3230
- console.log(chalk14.red(` \u2717 ${check.name}: not found`));
2235
+ console.log(chalk13.red(` \u2717 ${check.name}: not found`));
3231
2236
  allOk = false;
3232
2237
  }
3233
2238
  }
3234
2239
  console.log();
3235
- console.log(chalk14.cyan("Recommended:"));
2240
+ console.log(chalk13.cyan("Recommended:"));
3236
2241
  for (const check of recommended) {
3237
2242
  const result = checkCommand(check);
3238
2243
  if (result.found) {
3239
- console.log(chalk14.green(` \u2713 ${check.name}: ${result.version}`));
2244
+ console.log(chalk13.green(` \u2713 ${check.name}: ${result.version}`));
3240
2245
  } else {
3241
- console.log(chalk14.dim(` - ${check.name}: not found`));
2246
+ console.log(chalk13.dim(` - ${check.name}: not found`));
3242
2247
  }
3243
2248
  }
3244
2249
  if (config?.tools && Object.keys(config.tools).length > 0) {
3245
2250
  console.log();
3246
- console.log(chalk14.cyan("Hub tools (from hub.yaml):"));
2251
+ console.log(chalk13.cyan("Hub tools (from hub.yaml):"));
3247
2252
  for (const [tool, expected] of Object.entries(config.tools)) {
3248
2253
  const actual = getToolVersion(tool);
3249
2254
  if (!actual) {
3250
- console.log(chalk14.red(` \u2717 ${tool}: not found (expected ${expected})`));
2255
+ console.log(chalk13.red(` \u2717 ${tool}: not found (expected ${expected})`));
3251
2256
  allOk = false;
3252
2257
  } else if (versionMatches(actual, expected)) {
3253
- console.log(chalk14.green(` \u2713 ${tool}: ${actual} (expected ${expected})`));
2258
+ console.log(chalk13.green(` \u2713 ${tool}: ${actual} (expected ${expected})`));
3254
2259
  } else {
3255
- console.log(chalk14.yellow(` \u26A0 ${tool}: ${actual} (expected ${expected})`));
2260
+ console.log(chalk13.yellow(` \u26A0 ${tool}: ${actual} (expected ${expected})`));
3256
2261
  }
3257
2262
  }
3258
2263
  }
@@ -3262,22 +2267,22 @@ var doctorCommand = new Command14("doctor").description("Check required dependen
3262
2267
  );
3263
2268
  if (reposWithTools.length > 0) {
3264
2269
  console.log();
3265
- console.log(chalk14.cyan("Repo-specific tools:"));
2270
+ console.log(chalk13.cyan("Repo-specific tools:"));
3266
2271
  for (const repo of reposWithTools) {
3267
- const repoDir = join15(hubDir, repo.path);
3268
- if (!existsSync12(repoDir)) {
3269
- console.log(chalk14.dim(` ${repo.name}: not cloned, skipping`));
2272
+ const repoDir = join13(hubDir, repo.path);
2273
+ if (!existsSync11(repoDir)) {
2274
+ console.log(chalk13.dim(` ${repo.name}: not cloned, skipping`));
3270
2275
  continue;
3271
2276
  }
3272
- console.log(chalk14.yellow(` \u25B8 ${repo.name}`));
2277
+ console.log(chalk13.yellow(` \u25B8 ${repo.name}`));
3273
2278
  for (const [tool, expected] of Object.entries(repo.tools)) {
3274
2279
  const actual = getToolVersion(tool);
3275
2280
  if (!actual) {
3276
- console.log(chalk14.red(` \u2717 ${tool}: not found (expected ${expected})`));
2281
+ console.log(chalk13.red(` \u2717 ${tool}: not found (expected ${expected})`));
3277
2282
  } else if (versionMatches(actual, expected)) {
3278
- console.log(chalk14.green(` \u2713 ${tool}: ${actual} (expected ${expected})`));
2283
+ console.log(chalk13.green(` \u2713 ${tool}: ${actual} (expected ${expected})`));
3279
2284
  } else {
3280
- console.log(chalk14.yellow(` \u26A0 ${tool}: ${actual} (expected ${expected})`));
2285
+ console.log(chalk13.yellow(` \u26A0 ${tool}: ${actual} (expected ${expected})`));
3281
2286
  }
3282
2287
  }
3283
2288
  }
@@ -3285,23 +2290,23 @@ var doctorCommand = new Command14("doctor").description("Check required dependen
3285
2290
  }
3286
2291
  console.log();
3287
2292
  if (allOk) {
3288
- console.log(chalk14.green("All checks passed!\n"));
2293
+ console.log(chalk13.green("All checks passed!\n"));
3289
2294
  } else {
3290
- console.log(chalk14.red("Some checks failed.\n"));
2295
+ console.log(chalk13.red("Some checks failed.\n"));
3291
2296
  if (config?.tools) {
3292
- console.log(chalk14.cyan("Fix with: hub tools install\n"));
2297
+ console.log(chalk13.cyan("Fix with: hub tools install\n"));
3293
2298
  }
3294
2299
  process.exit(1);
3295
2300
  }
3296
2301
  });
3297
2302
 
3298
2303
  // src/commands/tools.ts
3299
- import { Command as Command15 } from "commander";
3300
- import { existsSync as existsSync13 } from "fs";
3301
- import { writeFile as writeFile10 } from "fs/promises";
3302
- import { join as join16 } from "path";
2304
+ import { Command as Command14 } from "commander";
2305
+ import { existsSync as existsSync12 } from "fs";
2306
+ import { writeFile as writeFile9 } from "fs/promises";
2307
+ import { join as join14 } from "path";
3303
2308
  import { execSync as execSync11 } from "child_process";
3304
- import chalk15 from "chalk";
2309
+ import chalk14 from "chalk";
3305
2310
  function hasMise2() {
3306
2311
  try {
3307
2312
  execSync11("mise --version", { stdio: ["pipe", "pipe", "pipe"] });
@@ -3338,148 +2343,148 @@ async function generateMiseFiles(config, hubDir) {
3338
2343
  let count = 0;
3339
2344
  if (config.tools && Object.keys(config.tools).length > 0) {
3340
2345
  const content = generateMiseToml2(config.tools, config.mise_settings);
3341
- await writeFile10(join16(hubDir, ".mise.toml"), content, "utf-8");
3342
- console.log(chalk15.green(` Generated .mise.toml (${Object.keys(config.tools).length} tools)`));
2346
+ await writeFile9(join14(hubDir, ".mise.toml"), content, "utf-8");
2347
+ console.log(chalk14.green(` Generated .mise.toml (${Object.keys(config.tools).length} tools)`));
3343
2348
  count++;
3344
2349
  }
3345
2350
  for (const repo of config.repos) {
3346
2351
  if (!repo.tools || Object.keys(repo.tools).length === 0) continue;
3347
- const repoDir = join16(hubDir, repo.path);
3348
- if (!existsSync13(repoDir)) {
3349
- console.log(chalk15.dim(` ${repo.name}: not cloned, skipping`));
2352
+ const repoDir = join14(hubDir, repo.path);
2353
+ if (!existsSync12(repoDir)) {
2354
+ console.log(chalk14.dim(` ${repo.name}: not cloned, skipping`));
3350
2355
  continue;
3351
2356
  }
3352
2357
  const merged = mergeTools(config.tools || {}, repo.tools);
3353
2358
  const content = generateMiseToml2(merged);
3354
- await writeFile10(join16(repoDir, ".mise.toml"), content, "utf-8");
3355
- console.log(chalk15.green(` ${repo.name}: Generated .mise.toml (${Object.keys(merged).length} tools)`));
2359
+ await writeFile9(join14(repoDir, ".mise.toml"), content, "utf-8");
2360
+ console.log(chalk14.green(` ${repo.name}: Generated .mise.toml (${Object.keys(merged).length} tools)`));
3356
2361
  count++;
3357
2362
  }
3358
2363
  return count;
3359
2364
  }
3360
- var toolsCommand = new Command15("tools").description("Manage development tool versions via mise").addCommand(
3361
- new Command15("install").description("Install all tools defined in hub.yaml using mise").option("--generate", "Generate .mise.toml files before installing").action(async (opts) => {
2365
+ var toolsCommand = new Command14("tools").description("Manage development tool versions via mise").addCommand(
2366
+ new Command14("install").description("Install all tools defined in hub.yaml using mise").option("--generate", "Generate .mise.toml files before installing").action(async (opts) => {
3362
2367
  const hubDir = process.cwd();
3363
2368
  const config = await loadHubConfig(hubDir);
3364
2369
  if (!hasMise2()) {
3365
- console.log(chalk15.red("\nmise is not installed."));
3366
- console.log(chalk15.cyan("Install with: curl https://mise.run | sh"));
3367
- console.log(chalk15.cyan("Or: brew install mise\n"));
2370
+ console.log(chalk14.red("\nmise is not installed."));
2371
+ console.log(chalk14.cyan("Install with: curl https://mise.run | sh"));
2372
+ console.log(chalk14.cyan("Or: brew install mise\n"));
3368
2373
  return;
3369
2374
  }
3370
2375
  if (!config.tools && !config.repos.some((r) => r.tools)) {
3371
- console.log(chalk15.yellow("\nNo tools defined in hub.yaml\n"));
2376
+ console.log(chalk14.yellow("\nNo tools defined in hub.yaml\n"));
3372
2377
  return;
3373
2378
  }
3374
- console.log(chalk15.blue("\n\u2501\u2501\u2501 Installing tools \u2501\u2501\u2501\n"));
2379
+ console.log(chalk14.blue("\n\u2501\u2501\u2501 Installing tools \u2501\u2501\u2501\n"));
3375
2380
  if (opts.generate) {
3376
2381
  await generateMiseFiles(config, hubDir);
3377
2382
  console.log();
3378
2383
  }
3379
2384
  if (config.tools && Object.keys(config.tools).length > 0) {
3380
- console.log(chalk15.cyan("Installing hub-level tools..."));
2385
+ console.log(chalk14.cyan("Installing hub-level tools..."));
3381
2386
  try {
3382
2387
  execSync11("mise trust && mise install", {
3383
2388
  cwd: hubDir,
3384
2389
  stdio: "inherit"
3385
2390
  });
3386
- console.log(chalk15.green(" Hub tools installed\n"));
2391
+ console.log(chalk14.green(" Hub tools installed\n"));
3387
2392
  } catch {
3388
- console.log(chalk15.red(" Failed to install hub tools\n"));
2393
+ console.log(chalk14.red(" Failed to install hub tools\n"));
3389
2394
  }
3390
2395
  }
3391
2396
  for (const repo of config.repos) {
3392
2397
  if (!repo.tools || Object.keys(repo.tools).length === 0) continue;
3393
- const repoDir = join16(hubDir, repo.path);
3394
- if (!existsSync13(repoDir)) {
3395
- console.log(chalk15.dim(` ${repo.name}: not cloned, skipping`));
2398
+ const repoDir = join14(hubDir, repo.path);
2399
+ if (!existsSync12(repoDir)) {
2400
+ console.log(chalk14.dim(` ${repo.name}: not cloned, skipping`));
3396
2401
  continue;
3397
2402
  }
3398
- console.log(chalk15.yellow(`\u25B8 ${repo.name}`));
2403
+ console.log(chalk14.yellow(`\u25B8 ${repo.name}`));
3399
2404
  try {
3400
2405
  execSync11("mise trust 2>/dev/null; mise install", {
3401
2406
  cwd: repoDir,
3402
2407
  stdio: "inherit"
3403
2408
  });
3404
- console.log(chalk15.green(" Tools installed"));
2409
+ console.log(chalk14.green(" Tools installed"));
3405
2410
  } catch {
3406
- console.log(chalk15.red(" Failed to install tools"));
2411
+ console.log(chalk14.red(" Failed to install tools"));
3407
2412
  }
3408
2413
  }
3409
- console.log(chalk15.green("\nAll tools installed!\n"));
3410
- console.log(chalk15.cyan("Make sure mise is activated in your shell:"));
2414
+ console.log(chalk14.green("\nAll tools installed!\n"));
2415
+ console.log(chalk14.cyan("Make sure mise is activated in your shell:"));
3411
2416
  console.log(' eval "$(mise activate zsh)" # zsh');
3412
2417
  console.log(' eval "$(mise activate bash)" # bash\n');
3413
2418
  })
3414
2419
  ).addCommand(
3415
- new Command15("generate").description("Generate .mise.toml files from hub.yaml").action(async () => {
2420
+ new Command14("generate").description("Generate .mise.toml files from hub.yaml").action(async () => {
3416
2421
  const hubDir = process.cwd();
3417
2422
  const config = await loadHubConfig(hubDir);
3418
2423
  if (!config.tools && !config.repos.some((r) => r.tools)) {
3419
- console.log(chalk15.yellow("\nNo tools defined in hub.yaml\n"));
2424
+ console.log(chalk14.yellow("\nNo tools defined in hub.yaml\n"));
3420
2425
  return;
3421
2426
  }
3422
- console.log(chalk15.blue("\n\u2501\u2501\u2501 Generating .mise.toml files \u2501\u2501\u2501\n"));
2427
+ console.log(chalk14.blue("\n\u2501\u2501\u2501 Generating .mise.toml files \u2501\u2501\u2501\n"));
3423
2428
  const count = await generateMiseFiles(config, hubDir);
3424
- console.log(chalk15.green(`
2429
+ console.log(chalk14.green(`
3425
2430
  Generated ${count} .mise.toml file(s)
3426
2431
  `));
3427
- console.log(chalk15.cyan("Install with: hub tools install\n"));
2432
+ console.log(chalk14.cyan("Install with: hub tools install\n"));
3428
2433
  })
3429
2434
  ).addCommand(
3430
- new Command15("check").description("Verify installed tool versions match hub.yaml").action(async () => {
2435
+ new Command14("check").description("Verify installed tool versions match hub.yaml").action(async () => {
3431
2436
  const hubDir = process.cwd();
3432
2437
  const config = await loadHubConfig(hubDir);
3433
2438
  if (!config.tools && !config.repos.some((r) => r.tools)) {
3434
- console.log(chalk15.yellow("\nNo tools defined in hub.yaml\n"));
2439
+ console.log(chalk14.yellow("\nNo tools defined in hub.yaml\n"));
3435
2440
  return;
3436
2441
  }
3437
- console.log(chalk15.blue("\n\u2501\u2501\u2501 Checking tool versions \u2501\u2501\u2501\n"));
2442
+ console.log(chalk14.blue("\n\u2501\u2501\u2501 Checking tool versions \u2501\u2501\u2501\n"));
3438
2443
  let allOk = true;
3439
2444
  if (config.tools) {
3440
- console.log(chalk15.cyan("Hub tools:"));
2445
+ console.log(chalk14.cyan("Hub tools:"));
3441
2446
  for (const [tool, expected] of Object.entries(config.tools)) {
3442
2447
  const actual = getInstalledVersion(tool);
3443
2448
  if (!actual) {
3444
- console.log(chalk15.red(` \u2717 ${tool}: not found (expected ${expected})`));
2449
+ console.log(chalk14.red(` \u2717 ${tool}: not found (expected ${expected})`));
3445
2450
  allOk = false;
3446
2451
  } else if (actual.includes(expected) || expected.includes(extractVersion(actual))) {
3447
- console.log(chalk15.green(` \u2713 ${tool} ${expected}`));
2452
+ console.log(chalk14.green(` \u2713 ${tool} ${expected}`));
3448
2453
  } else {
3449
- console.log(chalk15.yellow(` \u26A0 ${tool}: ${extractVersion(actual)} (expected ${expected})`));
2454
+ console.log(chalk14.yellow(` \u26A0 ${tool}: ${extractVersion(actual)} (expected ${expected})`));
3450
2455
  allOk = false;
3451
2456
  }
3452
2457
  }
3453
2458
  }
3454
2459
  for (const repo of config.repos) {
3455
2460
  if (!repo.tools || Object.keys(repo.tools).length === 0) continue;
3456
- const repoDir = join16(hubDir, repo.path);
3457
- if (!existsSync13(repoDir)) {
3458
- console.log(chalk15.dim(`
2461
+ const repoDir = join14(hubDir, repo.path);
2462
+ if (!existsSync12(repoDir)) {
2463
+ console.log(chalk14.dim(`
3459
2464
  ${repo.name}: not cloned`));
3460
2465
  continue;
3461
2466
  }
3462
- console.log(chalk15.yellow(`
2467
+ console.log(chalk14.yellow(`
3463
2468
  \u25B8 ${repo.name}`));
3464
2469
  for (const [tool, expected] of Object.entries(repo.tools)) {
3465
2470
  const actual = getInstalledVersion(tool);
3466
2471
  if (!actual) {
3467
- console.log(chalk15.red(` \u2717 ${tool}: not found (expected ${expected})`));
2472
+ console.log(chalk14.red(` \u2717 ${tool}: not found (expected ${expected})`));
3468
2473
  allOk = false;
3469
2474
  } else if (actual.includes(expected) || expected.includes(extractVersion(actual))) {
3470
- console.log(chalk15.green(` \u2713 ${tool} ${expected}`));
2475
+ console.log(chalk14.green(` \u2713 ${tool} ${expected}`));
3471
2476
  } else {
3472
- console.log(chalk15.yellow(` \u26A0 ${tool}: ${extractVersion(actual)} (expected ${expected})`));
2477
+ console.log(chalk14.yellow(` \u26A0 ${tool}: ${extractVersion(actual)} (expected ${expected})`));
3473
2478
  allOk = false;
3474
2479
  }
3475
2480
  }
3476
2481
  }
3477
2482
  console.log();
3478
2483
  if (allOk) {
3479
- console.log(chalk15.green("All tool versions match!\n"));
2484
+ console.log(chalk14.green("All tool versions match!\n"));
3480
2485
  } else {
3481
- console.log(chalk15.red("Some tools are missing or have wrong versions.\n"));
3482
- console.log(chalk15.cyan("Fix with: hub tools install --generate\n"));
2486
+ console.log(chalk14.red("Some tools are missing or have wrong versions.\n"));
2487
+ console.log(chalk14.cyan("Fix with: hub tools install --generate\n"));
3483
2488
  }
3484
2489
  })
3485
2490
  );
@@ -3513,24 +2518,24 @@ function extractVersion(s) {
3513
2518
  }
3514
2519
 
3515
2520
  // src/commands/memory.ts
3516
- import { Command as Command16 } from "commander";
3517
- import { existsSync as existsSync14 } from "fs";
3518
- import { mkdir as mkdir9, readdir as readdir6, readFile as readFile9, writeFile as writeFile11, rm as rm5, appendFile as appendFile2 } from "fs/promises";
3519
- import { join as join17, resolve as resolve6, basename as basename2 } from "path";
3520
- import chalk16 from "chalk";
2521
+ import { Command as Command15 } from "commander";
2522
+ import { existsSync as existsSync13 } from "fs";
2523
+ import { mkdir as mkdir8, readdir as readdir5, readFile as readFile7, writeFile as writeFile10, rm as rm5, appendFile as appendFile2 } from "fs/promises";
2524
+ import { join as join15, resolve as resolve5, basename as basename2 } from "path";
2525
+ import chalk15 from "chalk";
3521
2526
  async function ensureLanceDbIgnored(memoriesDir, hubDir) {
3522
2527
  const relative = memoriesDir.replace(hubDir + "/", "");
3523
2528
  const pattern = `${relative}/.lancedb/`;
3524
- const gitignorePath = join17(hubDir, ".gitignore");
3525
- if (existsSync14(gitignorePath)) {
3526
- const content = await readFile9(gitignorePath, "utf-8");
2529
+ const gitignorePath = join15(hubDir, ".gitignore");
2530
+ if (existsSync13(gitignorePath)) {
2531
+ const content = await readFile7(gitignorePath, "utf-8");
3527
2532
  if (content.includes(".lancedb")) return;
3528
2533
  await appendFile2(gitignorePath, `
3529
2534
  # Memory vector store (generated)
3530
2535
  ${pattern}
3531
2536
  `);
3532
2537
  } else {
3533
- await writeFile11(gitignorePath, `# Memory vector store (generated)
2538
+ await writeFile10(gitignorePath, `# Memory vector store (generated)
3534
2539
  ${pattern}
3535
2540
  `, "utf-8");
3536
2541
  }
@@ -3543,7 +2548,7 @@ var VALID_CATEGORIES = [
3543
2548
  "gotchas"
3544
2549
  ];
3545
2550
  function getMemoriesPath(hubDir, configPath) {
3546
- return resolve6(hubDir, configPath || "memories");
2551
+ return resolve5(hubDir, configPath || "memories");
3547
2552
  }
3548
2553
  function parseFrontmatter(raw) {
3549
2554
  const match = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
@@ -3575,20 +2580,20 @@ function buildFrontmatter(data) {
3575
2580
  return lines.join("\n");
3576
2581
  }
3577
2582
  async function listMemories(memoriesDir, opts) {
3578
- if (!existsSync14(memoriesDir)) {
3579
- console.log(chalk16.dim(" No memories directory found."));
2583
+ if (!existsSync13(memoriesDir)) {
2584
+ console.log(chalk15.dim(" No memories directory found."));
3580
2585
  return;
3581
2586
  }
3582
2587
  let total = 0;
3583
2588
  for (const cat of VALID_CATEGORIES) {
3584
2589
  if (opts.category && opts.category !== cat) continue;
3585
- const catDir = join17(memoriesDir, cat);
3586
- if (!existsSync14(catDir)) continue;
3587
- const files = (await readdir6(catDir)).filter((f) => f.endsWith(".md"));
2590
+ const catDir = join15(memoriesDir, cat);
2591
+ if (!existsSync13(catDir)) continue;
2592
+ const files = (await readdir5(catDir)).filter((f) => f.endsWith(".md"));
3588
2593
  if (files.length === 0) continue;
3589
2594
  const entries = [];
3590
2595
  for (const file of files) {
3591
- const raw = await readFile9(join17(catDir, file), "utf-8");
2596
+ const raw = await readFile7(join15(catDir, file), "utf-8");
3592
2597
  const { data } = parseFrontmatter(raw);
3593
2598
  const status = data.status || "active";
3594
2599
  if (opts.status && status !== opts.status) continue;
@@ -3601,29 +2606,29 @@ async function listMemories(memoriesDir, opts) {
3601
2606
  });
3602
2607
  }
3603
2608
  if (entries.length === 0) continue;
3604
- console.log(chalk16.cyan(`
2609
+ console.log(chalk15.cyan(`
3605
2610
  ${cat} (${entries.length})`));
3606
2611
  for (const e of entries) {
3607
- const statusIcon = e.status === "active" ? chalk16.green("\u25CF") : chalk16.dim("\u25CB");
3608
- const tags = e.tags.length > 0 ? chalk16.dim(` [${e.tags.join(", ")}]`) : "";
3609
- console.log(` ${statusIcon} ${chalk16.yellow(e.id)} \u2014 ${e.title} ${chalk16.dim(`(${e.date})`)}${tags}`);
2612
+ const statusIcon = e.status === "active" ? chalk15.green("\u25CF") : chalk15.dim("\u25CB");
2613
+ const tags = e.tags.length > 0 ? chalk15.dim(` [${e.tags.join(", ")}]`) : "";
2614
+ console.log(` ${statusIcon} ${chalk15.yellow(e.id)} \u2014 ${e.title} ${chalk15.dim(`(${e.date})`)}${tags}`);
3610
2615
  }
3611
2616
  total += entries.length;
3612
2617
  }
3613
2618
  if (total === 0) {
3614
- console.log(chalk16.dim(" No memories found."));
2619
+ console.log(chalk15.dim(" No memories found."));
3615
2620
  } else {
3616
- console.log(chalk16.green(`
2621
+ console.log(chalk15.green(`
3617
2622
  Total: ${total} memories
3618
2623
  `));
3619
2624
  }
3620
2625
  }
3621
- var memoryCommand = new Command16("memory").description("Manage team memories \u2014 persistent knowledge base for AI context").addCommand(
3622
- new Command16("add").description("Create a new memory entry").argument("<category>", `Category: ${VALID_CATEGORIES.join(", ")}`).argument("<title>", "Memory title").option("-c, --content <content>", "Memory content (or provide via stdin)").option("-t, --tags <tags>", "Comma-separated tags").option("-a, --author <author>", "Author name").action(
2626
+ var memoryCommand = new Command15("memory").description("Manage team memories \u2014 persistent knowledge base for AI context").addCommand(
2627
+ new Command15("add").description("Create a new memory entry").argument("<category>", `Category: ${VALID_CATEGORIES.join(", ")}`).argument("<title>", "Memory title").option("-c, --content <content>", "Memory content (or provide via stdin)").option("-t, --tags <tags>", "Comma-separated tags").option("-a, --author <author>", "Author name").action(
3623
2628
  async (category, title, opts) => {
3624
2629
  if (!VALID_CATEGORIES.includes(category)) {
3625
2630
  console.log(
3626
- chalk16.red(`
2631
+ chalk15.red(`
3627
2632
  Invalid category: ${category}. Valid: ${VALID_CATEGORIES.join(", ")}
3628
2633
  `)
3629
2634
  );
@@ -3637,13 +2642,13 @@ var memoryCommand = new Command16("memory").description("Manage team memories \u
3637
2642
  } catch {
3638
2643
  memoriesDir = getMemoriesPath(hubDir);
3639
2644
  }
3640
- const catDir = join17(memoriesDir, category);
3641
- await mkdir9(catDir, { recursive: true });
2645
+ const catDir = join15(memoriesDir, category);
2646
+ await mkdir8(catDir, { recursive: true });
3642
2647
  await ensureLanceDbIgnored(memoriesDir, hubDir);
3643
2648
  const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
3644
2649
  const slug = title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
3645
2650
  const id = `${date}-${slug}`;
3646
- const filePath = join17(catDir, `${id}.md`);
2651
+ const filePath = join15(catDir, `${id}.md`);
3647
2652
  const fm = {
3648
2653
  title,
3649
2654
  category,
@@ -3663,19 +2668,19 @@ var memoryCommand = new Command16("memory").description("Manage team memories \u
3663
2668
 
3664
2669
  ${content}
3665
2670
  `;
3666
- await writeFile11(filePath, fileContent, "utf-8");
3667
- console.log(chalk16.green(`
2671
+ await writeFile10(filePath, fileContent, "utf-8");
2672
+ console.log(chalk15.green(`
3668
2673
  Created: ${category}/${id}.md`));
3669
- console.log(chalk16.dim(` Path: ${filePath}`));
2674
+ console.log(chalk15.dim(` Path: ${filePath}`));
3670
2675
  if (!opts.content) {
3671
- console.log(chalk16.yellow(" Edit the file to add content.\n"));
2676
+ console.log(chalk15.yellow(" Edit the file to add content.\n"));
3672
2677
  } else {
3673
2678
  console.log();
3674
2679
  }
3675
2680
  }
3676
2681
  )
3677
2682
  ).addCommand(
3678
- new Command16("list").description("List all memories").option("-c, --category <category>", "Filter by category").option("-s, --status <status>", "Filter by status (active, archived, superseded)").action(async (opts) => {
2683
+ new Command15("list").description("List all memories").option("-c, --category <category>", "Filter by category").option("-s, --status <status>", "Filter by status (active, archived, superseded)").action(async (opts) => {
3679
2684
  const hubDir = process.cwd();
3680
2685
  let memoriesDir;
3681
2686
  try {
@@ -3684,11 +2689,11 @@ ${content}
3684
2689
  } catch {
3685
2690
  memoriesDir = getMemoriesPath(hubDir);
3686
2691
  }
3687
- console.log(chalk16.blue("\nTeam Memories"));
2692
+ console.log(chalk15.blue("\nTeam Memories"));
3688
2693
  await listMemories(memoriesDir, opts);
3689
2694
  })
3690
2695
  ).addCommand(
3691
- new Command16("archive").description("Archive a memory (soft-delete)").argument("<id>", "Memory ID (filename without .md)").action(async (id) => {
2696
+ new Command15("archive").description("Archive a memory (soft-delete)").argument("<id>", "Memory ID (filename without .md)").action(async (id) => {
3692
2697
  const hubDir = process.cwd();
3693
2698
  let memoriesDir;
3694
2699
  try {
@@ -3699,28 +2704,28 @@ ${content}
3699
2704
  }
3700
2705
  let found = false;
3701
2706
  for (const cat of VALID_CATEGORIES) {
3702
- const filePath = join17(memoriesDir, cat, `${id}.md`);
3703
- if (!existsSync14(filePath)) continue;
3704
- const raw = await readFile9(filePath, "utf-8");
2707
+ const filePath = join15(memoriesDir, cat, `${id}.md`);
2708
+ if (!existsSync13(filePath)) continue;
2709
+ const raw = await readFile7(filePath, "utf-8");
3705
2710
  const { data, content } = parseFrontmatter(raw);
3706
2711
  data.status = "archived";
3707
2712
  const updated = `${buildFrontmatter(data)}
3708
2713
  ${content}`;
3709
- await writeFile11(filePath, updated, "utf-8");
3710
- console.log(chalk16.green(`
2714
+ await writeFile10(filePath, updated, "utf-8");
2715
+ console.log(chalk15.green(`
3711
2716
  Archived: ${cat}/${id}.md
3712
2717
  `));
3713
2718
  found = true;
3714
2719
  break;
3715
2720
  }
3716
2721
  if (!found) {
3717
- console.log(chalk16.red(`
2722
+ console.log(chalk15.red(`
3718
2723
  Memory "${id}" not found.
3719
2724
  `));
3720
2725
  }
3721
2726
  })
3722
2727
  ).addCommand(
3723
- new Command16("remove").description("Permanently delete a memory").argument("<id>", "Memory ID (filename without .md)").action(async (id) => {
2728
+ new Command15("remove").description("Permanently delete a memory").argument("<id>", "Memory ID (filename without .md)").action(async (id) => {
3724
2729
  const hubDir = process.cwd();
3725
2730
  let memoriesDir;
3726
2731
  try {
@@ -3731,17 +2736,17 @@ ${content}`;
3731
2736
  }
3732
2737
  let found = false;
3733
2738
  for (const cat of VALID_CATEGORIES) {
3734
- const filePath = join17(memoriesDir, cat, `${id}.md`);
3735
- if (!existsSync14(filePath)) continue;
2739
+ const filePath = join15(memoriesDir, cat, `${id}.md`);
2740
+ if (!existsSync13(filePath)) continue;
3736
2741
  await rm5(filePath);
3737
- console.log(chalk16.green(`
2742
+ console.log(chalk15.green(`
3738
2743
  Removed: ${cat}/${id}.md
3739
2744
  `));
3740
2745
  found = true;
3741
2746
  break;
3742
2747
  }
3743
2748
  if (!found) {
3744
- console.log(chalk16.red(`
2749
+ console.log(chalk15.red(`
3745
2750
  Memory "${id}" not found.
3746
2751
  `));
3747
2752
  }
@@ -3749,16 +2754,16 @@ ${content}`;
3749
2754
  );
3750
2755
 
3751
2756
  // src/commands/update.ts
3752
- import { Command as Command17 } from "commander";
2757
+ import { Command as Command16 } from "commander";
3753
2758
  import { execSync as execSync12 } from "child_process";
3754
2759
  import { readFileSync } from "fs";
3755
- import { join as join18, dirname } from "path";
2760
+ import { join as join16, dirname } from "path";
3756
2761
  import { fileURLToPath } from "url";
3757
- import chalk17 from "chalk";
2762
+ import chalk16 from "chalk";
3758
2763
  var PACKAGE_NAME = "@arvoretech/hub";
3759
2764
  function getCurrentVersion() {
3760
2765
  const __dirname = dirname(fileURLToPath(import.meta.url));
3761
- const pkgPath = join18(__dirname, "..", "package.json");
2766
+ const pkgPath = join16(__dirname, "..", "package.json");
3762
2767
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
3763
2768
  return pkg.version;
3764
2769
  }
@@ -3781,77 +2786,77 @@ function detectPackageManager() {
3781
2786
  }
3782
2787
  }
3783
2788
  }
3784
- var updateCommand = new Command17("update").description("Update hub CLI to the latest version").option("--check", "Only check for updates without installing").action(async (opts) => {
2789
+ var updateCommand = new Command16("update").description("Update hub CLI to the latest version").option("--check", "Only check for updates without installing").action(async (opts) => {
3785
2790
  const currentVersion = getCurrentVersion();
3786
- console.log(chalk17.blue(`
2791
+ console.log(chalk16.blue(`
3787
2792
  Current version: ${currentVersion}`));
3788
2793
  let latestVersion;
3789
2794
  try {
3790
2795
  latestVersion = await getLatestVersion();
3791
2796
  } catch (err) {
3792
- console.log(chalk17.red(` Failed to check for updates: ${err.message}
2797
+ console.log(chalk16.red(` Failed to check for updates: ${err.message}
3793
2798
  `));
3794
2799
  return;
3795
2800
  }
3796
- console.log(chalk17.blue(` Latest version: ${latestVersion}`));
2801
+ console.log(chalk16.blue(` Latest version: ${latestVersion}`));
3797
2802
  if (currentVersion === latestVersion) {
3798
- console.log(chalk17.green("\n You're already on the latest version.\n"));
2803
+ console.log(chalk16.green("\n You're already on the latest version.\n"));
3799
2804
  return;
3800
2805
  }
3801
- console.log(chalk17.yellow(`
2806
+ console.log(chalk16.yellow(`
3802
2807
  Update available: ${currentVersion} \u2192 ${latestVersion}`));
3803
2808
  if (opts.check) {
3804
2809
  const pm2 = detectPackageManager();
3805
- console.log(chalk17.dim(`
2810
+ console.log(chalk16.dim(`
3806
2811
  Run 'hub update' or '${pm2} install -g ${PACKAGE_NAME}@latest' to update.
3807
2812
  `));
3808
2813
  return;
3809
2814
  }
3810
2815
  const pm = detectPackageManager();
3811
2816
  const installCmd = pm === "pnpm" ? `pnpm install -g ${PACKAGE_NAME}@latest` : pm === "yarn" ? `yarn global add ${PACKAGE_NAME}@latest` : `npm install -g ${PACKAGE_NAME}@latest`;
3812
- console.log(chalk17.cyan(`
2817
+ console.log(chalk16.cyan(`
3813
2818
  Updating with ${pm}...
3814
2819
  `));
3815
- console.log(chalk17.dim(` $ ${installCmd}
2820
+ console.log(chalk16.dim(` $ ${installCmd}
3816
2821
  `));
3817
2822
  try {
3818
2823
  execSync12(installCmd, { stdio: "inherit" });
3819
- console.log(chalk17.green(`
2824
+ console.log(chalk16.green(`
3820
2825
  Updated to ${latestVersion} successfully.
3821
2826
  `));
3822
2827
  } catch {
3823
- console.log(chalk17.red(`
2828
+ console.log(chalk16.red(`
3824
2829
  Update failed. Try running manually:`));
3825
- console.log(chalk17.dim(` $ ${installCmd}
2830
+ console.log(chalk16.dim(` $ ${installCmd}
3826
2831
  `));
3827
2832
  }
3828
2833
  });
3829
2834
 
3830
2835
  // src/commands/directory.ts
3831
- import { Command as Command18 } from "commander";
3832
- import chalk18 from "chalk";
3833
- var BASE_URL = "https://rhm-website.vercel.app/directory";
3834
- var directoryCommand = new Command18("directory").alias("dir").description("Browse the Repo Hub directory of skills, agents, hooks, and commands").argument("[query]", "Search term").option("-t, --type <type>", "Filter by type (skill, agent, hook, command)").action(async (query, opts) => {
2836
+ import { Command as Command17 } from "commander";
2837
+ import chalk17 from "chalk";
2838
+ var BASE_URL = "https://hub.arvore.com.br/directory";
2839
+ var directoryCommand = new Command17("directory").alias("dir").description("Browse the Repo Hub directory of skills, agents, hooks, and commands").argument("[query]", "Search term").option("-t, --type <type>", "Filter by type (skill, agent, hook, command)").action(async (query, opts) => {
3835
2840
  const params = new URLSearchParams();
3836
2841
  if (opts?.type) params.set("type", opts.type);
3837
2842
  if (query) params.set("q", query);
3838
2843
  const qs = params.toString();
3839
2844
  const url = qs ? `${BASE_URL}?${qs}` : BASE_URL;
3840
- console.log(chalk18.blue("\n Repo Hub Directory\n"));
3841
- console.log(chalk18.cyan(` ${url}
3842
- `));
3843
- console.log(chalk18.dim(" Install examples:"));
3844
- console.log(chalk18.dim(" hub skills add <owner>/<repo>/<skill>"));
3845
- console.log(chalk18.dim(" hub agents add <owner>/<repo>"));
3846
- console.log(chalk18.dim(" hub hooks add <owner>/<repo>"));
3847
- console.log(chalk18.dim(" hub commands add <owner>/<repo>\n"));
2845
+ console.log(chalk17.blue("\n Repo Hub Directory\n"));
2846
+ console.log(chalk17.cyan(` ${url}
2847
+ `));
2848
+ console.log(chalk17.dim(" Install examples:"));
2849
+ console.log(chalk17.dim(" hub skills add <owner>/<repo>/<skill>"));
2850
+ console.log(chalk17.dim(" hub agents add <owner>/<repo>"));
2851
+ console.log(chalk17.dim(" hub hooks add <owner>/<repo>"));
2852
+ console.log(chalk17.dim(" hub commands add <owner>/<repo>\n"));
3848
2853
  });
3849
2854
 
3850
2855
  // src/index.ts
3851
- var program = new Command19();
2856
+ var program = new Command18();
3852
2857
  program.name("hub").description(
3853
2858
  "Give your AI coding assistant the full picture. Multi-repo context, agent orchestration, and end-to-end workflows."
3854
- ).version("0.6.0").enablePositionalOptions();
2859
+ ).version("0.6.2").enablePositionalOptions();
3855
2860
  program.addCommand(initCommand);
3856
2861
  program.addCommand(addRepoCommand);
3857
2862
  program.addCommand(setupCommand);