@arkhera30/cli 0.1.15 → 0.1.16

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.
Files changed (2) hide show
  1. package/dist/index.js +42 -8
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -611,6 +611,16 @@ function mergeAndWriteConfig(configPath, mcpServers) {
611
611
  mkdirSync2(dir, { recursive: true });
612
612
  writeFileSync3(configPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
613
613
  }
614
+ function getMcpRemoteWrapperPath() {
615
+ return join3(homedir3(), ".forge", "bin", "mcp-remote-wrapper");
616
+ }
617
+ function buildStdioServers(config, wrapperPath, host) {
618
+ return {
619
+ anvil: { command: wrapperPath, args: [`http://${host}:${config.ports.anvil}/mcp`] },
620
+ vault: { command: wrapperPath, args: [`http://${host}:${config.ports.vault_mcp}/mcp`] },
621
+ forge: { command: wrapperPath, args: [`http://${host}:${config.ports.forge}/mcp`] }
622
+ };
623
+ }
614
624
  async function isClaudeCliAvailable() {
615
625
  try {
616
626
  const result = await execa2("claude", ["--version"], { reject: false });
@@ -657,21 +667,25 @@ async function syncSkills(runtime) {
657
667
  async function syncSkillsForCursor(runtime) {
658
668
  const home = homedir3();
659
669
  const rulesDir = join3(home, ".cursor", "rules");
670
+ const skillsBase = join3(home, ".cursor", "skills-cursor");
660
671
  const skills = ["horus-anvil", "horus-vault", "horus-forge"];
661
672
  const forgeContainer = "horus-forge-1";
662
673
  mkdirSync2(rulesDir, { recursive: true });
663
674
  for (const skill of skills) {
664
675
  const src = `/home/forge/.claude/skills/${skill}/SKILL.md`;
665
- const dest = join3(rulesDir, `${skill}.mdc`);
666
676
  const result = await runtime.exec(forgeContainer, "cat", src);
667
677
  if (result.exitCode === 0 && result.stdout.trim()) {
678
+ const ruleDest = join3(rulesDir, `${skill}.mdc`);
668
679
  const frontmatter = `---
669
680
  description: Horus ${skill} reference
670
681
  alwaysApply: true
671
682
  ---
672
683
 
673
684
  `;
674
- writeFileSync3(dest, frontmatter + result.stdout, "utf-8");
685
+ writeFileSync3(ruleDest, frontmatter + result.stdout, "utf-8");
686
+ const skillDir = join3(skillsBase, skill);
687
+ mkdirSync2(skillDir, { recursive: true });
688
+ writeFileSync3(join3(skillDir, "SKILL.md"), result.stdout, "utf-8");
675
689
  }
676
690
  }
677
691
  }
@@ -694,18 +708,38 @@ function printNextSteps(targets) {
694
708
  console.log("");
695
709
  }
696
710
  async function runConnect(config, runtime, targets, host = "localhost") {
697
- const mcpServers = {
711
+ const httpServers = {
698
712
  anvil: { url: `http://${host}:${config.ports.anvil}/sse` },
699
713
  vault: { url: `http://${host}:${config.ports.vault_mcp}/sse` },
700
714
  forge: { url: `http://${host}:${config.ports.forge}/sse` }
701
715
  };
702
716
  const configured = [];
703
717
  for (const target of targets) {
704
- if (target === "claude-code") {
718
+ if (target === "claude-desktop") {
719
+ const desktopSpinner = ora(`Configuring ${chalk.cyan("claude-desktop")}...`).start();
720
+ const wrapperPath = getMcpRemoteWrapperPath();
721
+ if (!existsSync4(wrapperPath)) {
722
+ desktopSpinner.fail("mcp-remote-wrapper not found");
723
+ console.log(chalk.dim(`Expected at: ${wrapperPath}`));
724
+ console.log(chalk.dim("Install it with: npx --yes mcp-remote --help"));
725
+ console.log(chalk.dim("Then place the wrapper script at the path above."));
726
+ continue;
727
+ }
728
+ try {
729
+ const stdioServers = buildStdioServers(config, wrapperPath, host);
730
+ const configPath = getConfigPath(target);
731
+ mergeAndWriteConfig(configPath, stdioServers);
732
+ desktopSpinner.succeed(`Configured ${chalk.cyan("claude-desktop")} \u2014 ${chalk.dim(configPath)}`);
733
+ configured.push(target);
734
+ } catch (error) {
735
+ desktopSpinner.fail("Failed to configure claude-desktop");
736
+ console.log(chalk.dim(error.message));
737
+ }
738
+ } else if (target === "claude-code") {
705
739
  const cliSpinner = ora("Registering MCP servers with Claude Code CLI...").start();
706
740
  const cliAvailable = await isClaudeCliAvailable();
707
741
  if (cliAvailable) {
708
- const { registered, failed } = await registerWithClaudeCode(mcpServers);
742
+ const { registered, failed } = await registerWithClaudeCode(httpServers);
709
743
  if (failed.length === 0) {
710
744
  cliSpinner.succeed(
711
745
  `Registered with Claude Code: ${registered.map((n) => chalk.cyan(n)).join(", ")}`
@@ -721,7 +755,7 @@ async function runConnect(config, runtime, targets, host = "localhost") {
721
755
  }
722
756
  } else {
723
757
  cliSpinner.warn("claude CLI not found on PATH \u2014 register manually:");
724
- for (const [name, entry] of Object.entries(mcpServers)) {
758
+ for (const [name, entry] of Object.entries(httpServers)) {
725
759
  const baseUrl = entry.url.replace(/\/sse$/, "");
726
760
  console.log(
727
761
  chalk.dim(` claude mcp add --transport http --scope user ${name} ${baseUrl}`)
@@ -732,7 +766,7 @@ async function runConnect(config, runtime, targets, host = "localhost") {
732
766
  const configPath = getConfigPath(target);
733
767
  const writeSpinner = ora(`Configuring ${chalk.cyan(target)}...`).start();
734
768
  try {
735
- mergeAndWriteConfig(configPath, mcpServers);
769
+ mergeAndWriteConfig(configPath, httpServers);
736
770
  writeSpinner.succeed(`Configured ${chalk.cyan(target)} \u2014 ${chalk.dim(configPath)}`);
737
771
  configured.push(target);
738
772
  } catch (error) {
@@ -755,7 +789,7 @@ async function runConnect(config, runtime, targets, host = "localhost") {
755
789
  const cursorRulesSpinner = ora("Syncing horus-core rules for Cursor...").start();
756
790
  try {
757
791
  await syncSkillsForCursor(runtime);
758
- cursorRulesSpinner.succeed("horus-core rules synced to ~/.cursor/rules/");
792
+ cursorRulesSpinner.succeed("horus-core rules synced to ~/.cursor/rules/ and skills to ~/.cursor/skills-cursor/");
759
793
  } catch (error) {
760
794
  cursorRulesSpinner.warn("Could not sync Cursor rules (Forge container may not be running)");
761
795
  console.log(chalk.dim(error.message));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkhera30/cli",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "CLI for managing the Horus AI development stack",
5
5
  "type": "module",
6
6
  "bin": {