@arkhera30/cli 0.1.14 → 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.
- package/dist/index.js +43 -8
- 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 });
|
|
@@ -624,6 +634,7 @@ async function registerWithClaudeCode(mcpServers) {
|
|
|
624
634
|
const failed = [];
|
|
625
635
|
for (const [name, entry] of Object.entries(mcpServers)) {
|
|
626
636
|
const baseUrl = entry.url.replace(/\/sse$/, "");
|
|
637
|
+
await execa2("claude", ["mcp", "remove", "--scope", "user", name], { reject: false });
|
|
627
638
|
const result = await execa2(
|
|
628
639
|
"claude",
|
|
629
640
|
["mcp", "add", "--transport", "http", "--scope", "user", name, baseUrl],
|
|
@@ -656,21 +667,25 @@ async function syncSkills(runtime) {
|
|
|
656
667
|
async function syncSkillsForCursor(runtime) {
|
|
657
668
|
const home = homedir3();
|
|
658
669
|
const rulesDir = join3(home, ".cursor", "rules");
|
|
670
|
+
const skillsBase = join3(home, ".cursor", "skills-cursor");
|
|
659
671
|
const skills = ["horus-anvil", "horus-vault", "horus-forge"];
|
|
660
672
|
const forgeContainer = "horus-forge-1";
|
|
661
673
|
mkdirSync2(rulesDir, { recursive: true });
|
|
662
674
|
for (const skill of skills) {
|
|
663
675
|
const src = `/home/forge/.claude/skills/${skill}/SKILL.md`;
|
|
664
|
-
const dest = join3(rulesDir, `${skill}.mdc`);
|
|
665
676
|
const result = await runtime.exec(forgeContainer, "cat", src);
|
|
666
677
|
if (result.exitCode === 0 && result.stdout.trim()) {
|
|
678
|
+
const ruleDest = join3(rulesDir, `${skill}.mdc`);
|
|
667
679
|
const frontmatter = `---
|
|
668
680
|
description: Horus ${skill} reference
|
|
669
681
|
alwaysApply: true
|
|
670
682
|
---
|
|
671
683
|
|
|
672
684
|
`;
|
|
673
|
-
writeFileSync3(
|
|
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");
|
|
674
689
|
}
|
|
675
690
|
}
|
|
676
691
|
}
|
|
@@ -693,18 +708,38 @@ function printNextSteps(targets) {
|
|
|
693
708
|
console.log("");
|
|
694
709
|
}
|
|
695
710
|
async function runConnect(config, runtime, targets, host = "localhost") {
|
|
696
|
-
const
|
|
711
|
+
const httpServers = {
|
|
697
712
|
anvil: { url: `http://${host}:${config.ports.anvil}/sse` },
|
|
698
713
|
vault: { url: `http://${host}:${config.ports.vault_mcp}/sse` },
|
|
699
714
|
forge: { url: `http://${host}:${config.ports.forge}/sse` }
|
|
700
715
|
};
|
|
701
716
|
const configured = [];
|
|
702
717
|
for (const target of targets) {
|
|
703
|
-
if (target === "claude-
|
|
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") {
|
|
704
739
|
const cliSpinner = ora("Registering MCP servers with Claude Code CLI...").start();
|
|
705
740
|
const cliAvailable = await isClaudeCliAvailable();
|
|
706
741
|
if (cliAvailable) {
|
|
707
|
-
const { registered, failed } = await registerWithClaudeCode(
|
|
742
|
+
const { registered, failed } = await registerWithClaudeCode(httpServers);
|
|
708
743
|
if (failed.length === 0) {
|
|
709
744
|
cliSpinner.succeed(
|
|
710
745
|
`Registered with Claude Code: ${registered.map((n) => chalk.cyan(n)).join(", ")}`
|
|
@@ -720,7 +755,7 @@ async function runConnect(config, runtime, targets, host = "localhost") {
|
|
|
720
755
|
}
|
|
721
756
|
} else {
|
|
722
757
|
cliSpinner.warn("claude CLI not found on PATH \u2014 register manually:");
|
|
723
|
-
for (const [name, entry] of Object.entries(
|
|
758
|
+
for (const [name, entry] of Object.entries(httpServers)) {
|
|
724
759
|
const baseUrl = entry.url.replace(/\/sse$/, "");
|
|
725
760
|
console.log(
|
|
726
761
|
chalk.dim(` claude mcp add --transport http --scope user ${name} ${baseUrl}`)
|
|
@@ -731,7 +766,7 @@ async function runConnect(config, runtime, targets, host = "localhost") {
|
|
|
731
766
|
const configPath = getConfigPath(target);
|
|
732
767
|
const writeSpinner = ora(`Configuring ${chalk.cyan(target)}...`).start();
|
|
733
768
|
try {
|
|
734
|
-
mergeAndWriteConfig(configPath,
|
|
769
|
+
mergeAndWriteConfig(configPath, httpServers);
|
|
735
770
|
writeSpinner.succeed(`Configured ${chalk.cyan(target)} \u2014 ${chalk.dim(configPath)}`);
|
|
736
771
|
configured.push(target);
|
|
737
772
|
} catch (error) {
|
|
@@ -754,7 +789,7 @@ async function runConnect(config, runtime, targets, host = "localhost") {
|
|
|
754
789
|
const cursorRulesSpinner = ora("Syncing horus-core rules for Cursor...").start();
|
|
755
790
|
try {
|
|
756
791
|
await syncSkillsForCursor(runtime);
|
|
757
|
-
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/");
|
|
758
793
|
} catch (error) {
|
|
759
794
|
cursorRulesSpinner.warn("Could not sync Cursor rules (Forge container may not be running)");
|
|
760
795
|
console.log(chalk.dim(error.message));
|