@elnora-ai/cli 1.5.0 → 1.5.4

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/cli.js +100 -50
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -25,7 +25,7 @@ var VERSION, PRODUCTION_BASE_URL, BASE_URL, AI_SERVER_URL, ENDPOINTS, DEFAULT_HE
25
25
  var init_config = __esm({
26
26
  "src/lib/config.ts"() {
27
27
  "use strict";
28
- VERSION = true ? "1.5.0" : process.env.npm_package_version ?? "0.0.0-dev";
28
+ VERSION = true ? "1.5.4" : process.env.npm_package_version ?? "0.0.0-dev";
29
29
  PRODUCTION_BASE_URL = "https://platform.elnora.ai/api/v1";
30
30
  BASE_URL = process.env.ELNORA_API_URL ?? PRODUCTION_BASE_URL;
31
31
  AI_SERVER_URL = process.env.ELNORA_AI_SERVER_URL ?? "https://platform.elnora.ai/ai-server";
@@ -134,7 +134,10 @@ function scrub(text) {
134
134
  }
135
135
  }
136
136
  result = result.replace(SCRUB_KEY_VALUE_RE, "[REDACTED]");
137
- result = result.replace(SCRUB_LONG_TOKEN_RE, "[REDACTED]");
137
+ result = result.replace(SCRUB_LONG_TOKEN_RE, (match) => {
138
+ if (match.startsWith("elnora_live_")) return "[REDACTED]";
139
+ return /\d/.test(match) ? "[REDACTED]" : match;
140
+ });
138
141
  return result;
139
142
  }
140
143
  function scrubData(obj) {
@@ -1293,14 +1296,15 @@ var VSCODE_DIR = join2(HOME, ".vscode");
1293
1296
  var CODEX_DIR = join2(HOME, ".codex");
1294
1297
  var MARKETPLACE_NAME = "elnora-plugins";
1295
1298
  var MARKETPLACE_REPO = "Elnora-AI/elnora-plugins";
1299
+ var MARKETPLACE_GITHUB_URL = `https://github.com/${MARKETPLACE_REPO}`;
1296
1300
  var PLUGIN_ID = `elnora@${MARKETPLACE_NAME}`;
1297
- var LEGACY_PLUGIN_IDS = ["elnora@elnora-local", "elnora@elnora-ai"];
1298
- var LEGACY_MARKETPLACE_NAMES = ["elnora-local", "elnora-ai"];
1299
1301
  function readJsonFile(path) {
1302
+ if (!existsSync2(path)) return {};
1300
1303
  try {
1301
1304
  return JSON.parse(readFileSync2(path, "utf-8"));
1302
- } catch {
1303
- return {};
1305
+ } catch (err) {
1306
+ const reason = err instanceof Error ? err.message : String(err);
1307
+ throw new Error(`Cannot parse JSON config at ${path}: ${reason}`);
1304
1308
  }
1305
1309
  }
1306
1310
  function writeJsonFile(path, data) {
@@ -1756,8 +1760,27 @@ function addOpenCommand(program2) {
1756
1760
  init_profiles();
1757
1761
 
1758
1762
  // src/lib/setup/claude.ts
1763
+ import { spawn } from "node:child_process";
1759
1764
  import { existsSync as existsSync5 } from "node:fs";
1760
- function setupClaude() {
1765
+ function runClaudeCli(args) {
1766
+ return new Promise((resolve, reject) => {
1767
+ const child = spawn("claude", args, {
1768
+ stdio: "inherit",
1769
+ shell: process.platform === "win32"
1770
+ });
1771
+ child.on("error", (err) => reject(err));
1772
+ child.on("close", (code) => {
1773
+ if (code === 0) {
1774
+ resolve();
1775
+ return;
1776
+ }
1777
+ const err = new Error(`claude ${args.join(" ")} exited with code ${code}`);
1778
+ err.code = code ?? -1;
1779
+ reject(err);
1780
+ });
1781
+ });
1782
+ }
1783
+ async function setupClaude() {
1761
1784
  if (!existsSync5(CLAUDE_DIR)) {
1762
1785
  console.error(fail("Claude Code not found (~/.claude/ does not exist)"));
1763
1786
  console.error("");
@@ -1765,34 +1788,40 @@ function setupClaude() {
1765
1788
  return false;
1766
1789
  }
1767
1790
  console.error(ok("Claude Code found"));
1768
- const marketplaces = readJsonFile(CLAUDE_MARKETPLACES_FILE);
1769
- for (const old of LEGACY_MARKETPLACE_NAMES) {
1770
- delete marketplaces[old];
1771
- }
1772
- marketplaces[MARKETPLACE_NAME] = {
1773
- source: {
1774
- source: "github",
1775
- repo: MARKETPLACE_REPO
1776
- }
1777
- };
1778
- writeJsonFile(CLAUDE_MARKETPLACES_FILE, marketplaces);
1779
- console.error(ok(`Marketplace registered (GitHub: ${MARKETPLACE_REPO})`));
1780
- const settings = readJsonFile(CLAUDE_SETTINGS_FILE);
1781
- if (!settings.enabledPlugins || typeof settings.enabledPlugins !== "object") {
1782
- settings.enabledPlugins = {};
1783
- }
1784
- const plugins = settings.enabledPlugins;
1785
- for (const old of LEGACY_PLUGIN_IDS) {
1786
- delete plugins[old];
1787
- }
1788
- plugins[PLUGIN_ID] = true;
1789
- writeJsonFile(CLAUDE_SETTINGS_FILE, settings);
1790
- console.error(ok(`Plugin enabled (${PLUGIN_ID})`));
1791
+ try {
1792
+ await runClaudeCli(["plugin", "marketplace", "add", MARKETPLACE_GITHUB_URL]);
1793
+ } catch (err) {
1794
+ return reportClaudeCliError(err, "marketplace add");
1795
+ }
1796
+ try {
1797
+ await runClaudeCli(["plugin", "install", PLUGIN_ID]);
1798
+ } catch (err) {
1799
+ return reportClaudeCliError(err, "plugin install");
1800
+ }
1791
1801
  console.error("");
1792
1802
  console.error(" Elnora skills are now available in Claude Code.");
1793
1803
  console.error(" Restart Claude Code if it's currently running.");
1794
1804
  return true;
1795
1805
  }
1806
+ function reportClaudeCliError(err, step) {
1807
+ const e = err;
1808
+ if (e?.code === "ENOENT") {
1809
+ console.error("");
1810
+ console.error(fail("`claude` not found on PATH"));
1811
+ console.error("");
1812
+ console.error(" Install Claude Code first: https://claude.ai/code");
1813
+ console.error(" Then from a fresh terminal, run:");
1814
+ console.error(` claude plugin marketplace add ${MARKETPLACE_GITHUB_URL}`);
1815
+ console.error(` claude plugin install ${PLUGIN_ID}`);
1816
+ return false;
1817
+ }
1818
+ console.error("");
1819
+ console.error(fail(`Setup step "${step}" failed`));
1820
+ console.error(" To retry manually:");
1821
+ console.error(` claude plugin marketplace add ${MARKETPLACE_GITHUB_URL}`);
1822
+ console.error(` claude plugin install ${PLUGIN_ID}`);
1823
+ return false;
1824
+ }
1796
1825
 
1797
1826
  // src/lib/setup/codex.ts
1798
1827
  import { existsSync as existsSync6 } from "node:fs";
@@ -1806,7 +1835,14 @@ function setupCodex(apiKey) {
1806
1835
  return false;
1807
1836
  }
1808
1837
  console.error(ok("Codex CLI found"));
1809
- const config = readJsonFile(CODEX_MCP_FILE);
1838
+ let config;
1839
+ try {
1840
+ config = readJsonFile(CODEX_MCP_FILE);
1841
+ } catch (err) {
1842
+ console.error(fail(err instanceof Error ? err.message : String(err)));
1843
+ console.error(" Repair or delete the file and retry.");
1844
+ return false;
1845
+ }
1810
1846
  if (!config.mcpServers || typeof config.mcpServers !== "object") {
1811
1847
  config.mcpServers = {};
1812
1848
  }
@@ -1833,7 +1869,14 @@ function setupCursor(apiKey) {
1833
1869
  return false;
1834
1870
  }
1835
1871
  console.error(ok("Cursor found"));
1836
- const config = readJsonFile(CURSOR_MCP_GLOBAL);
1872
+ let config;
1873
+ try {
1874
+ config = readJsonFile(CURSOR_MCP_GLOBAL);
1875
+ } catch (err) {
1876
+ console.error(fail(err instanceof Error ? err.message : String(err)));
1877
+ console.error(" Repair or delete the file and retry.");
1878
+ return false;
1879
+ }
1837
1880
  if (!config.mcpServers || typeof config.mcpServers !== "object") {
1838
1881
  config.mcpServers = {};
1839
1882
  }
@@ -1863,7 +1906,14 @@ function setupVscode(apiKey) {
1863
1906
  return false;
1864
1907
  }
1865
1908
  console.error(ok("VS Code found"));
1866
- const config = readJsonFile(VSCODE_MCP_GLOBAL);
1909
+ let config;
1910
+ try {
1911
+ config = readJsonFile(VSCODE_MCP_GLOBAL);
1912
+ } catch (err) {
1913
+ console.error(fail(err instanceof Error ? err.message : String(err)));
1914
+ console.error(" Repair or delete the file and retry.");
1915
+ return false;
1916
+ }
1867
1917
  if (!config.servers || typeof config.servers !== "object") {
1868
1918
  config.servers = {};
1869
1919
  }
@@ -1885,11 +1935,11 @@ function setupVscode(apiKey) {
1885
1935
  // src/commands/setup.ts
1886
1936
  var PLATFORM_SETUP = {
1887
1937
  claude: () => setupClaude(),
1888
- cursor: (key) => setupCursor(key),
1889
- vscode: (key) => setupVscode(key),
1890
- codex: (key) => setupCodex(key)
1938
+ cursor: async (key) => setupCursor(key),
1939
+ vscode: async (key) => setupVscode(key),
1940
+ codex: async (key) => setupCodex(key)
1891
1941
  };
1892
- function runSetup(platforms, profileName) {
1942
+ async function runSetup(platforms, profileName) {
1893
1943
  let apiKey;
1894
1944
  const needsKey = platforms.some((p) => p !== "claude");
1895
1945
  if (needsKey) {
@@ -1906,7 +1956,7 @@ function runSetup(platforms, profileName) {
1906
1956
  let anyFailed = false;
1907
1957
  for (const platform of platforms) {
1908
1958
  const setupFn = PLATFORM_SETUP[platform];
1909
- const success = setupFn(apiKey ?? "");
1959
+ const success = await setupFn(apiKey ?? "");
1910
1960
  if (!success) anyFailed = true;
1911
1961
  console.error("");
1912
1962
  }
@@ -1916,27 +1966,27 @@ function runSetup(platforms, profileName) {
1916
1966
  }
1917
1967
  function addSetupCommand(program2) {
1918
1968
  const setup = program2.command("setup").description("Configure AI coding tools to use Elnora").option("--profile <name>", "API key profile to use", "default");
1919
- setup.command("claude").description("Set up Claude Code (skills + MCP server)").action(() => {
1969
+ setup.command("claude").description("Set up Claude Code (skills + MCP server)").action(async () => {
1920
1970
  const opts = setup.opts();
1921
1971
  console.error("");
1922
- runSetup(["claude"], opts.profile);
1972
+ await runSetup(["claude"], opts.profile);
1923
1973
  });
1924
- setup.command("cursor").description("Set up Cursor (MCP server)").action(() => {
1974
+ setup.command("cursor").description("Set up Cursor (MCP server)").action(async () => {
1925
1975
  const opts = setup.opts();
1926
1976
  console.error("");
1927
- runSetup(["cursor"], opts.profile);
1977
+ await runSetup(["cursor"], opts.profile);
1928
1978
  });
1929
- setup.command("vscode").description("Set up VS Code Copilot (MCP server)").action(() => {
1979
+ setup.command("vscode").description("Set up VS Code Copilot (MCP server)").action(async () => {
1930
1980
  const opts = setup.opts();
1931
1981
  console.error("");
1932
- runSetup(["vscode"], opts.profile);
1982
+ await runSetup(["vscode"], opts.profile);
1933
1983
  });
1934
- setup.command("codex").description("Set up OpenAI Codex (MCP server)").action(() => {
1984
+ setup.command("codex").description("Set up OpenAI Codex (MCP server)").action(async () => {
1935
1985
  const opts = setup.opts();
1936
1986
  console.error("");
1937
- runSetup(["codex"], opts.profile);
1987
+ await runSetup(["codex"], opts.profile);
1938
1988
  });
1939
- setup.action(() => {
1989
+ setup.action(async () => {
1940
1990
  const opts = setup.opts();
1941
1991
  console.error("");
1942
1992
  const detected = detectPlatforms();
@@ -1955,11 +2005,11 @@ function addSetupCommand(program2) {
1955
2005
  }
1956
2006
  console.error("");
1957
2007
  const platforms = installed.map((p) => p.name);
1958
- runSetup(platforms, opts.profile);
2008
+ await runSetup(platforms, opts.profile);
1959
2009
  });
1960
- program2.command("setup-claude").description("Set up Claude Code (alias for 'setup claude')").option("--profile <name>", "API key profile to use", "default").action((opts) => {
2010
+ program2.command("setup-claude").description("Set up Claude Code (alias for 'setup claude')").option("--profile <name>", "API key profile to use", "default").action(async (opts) => {
1961
2011
  console.error("");
1962
- runSetup(["claude"], opts.profile);
2012
+ await runSetup(["claude"], opts.profile);
1963
2013
  });
1964
2014
  }
1965
2015
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elnora-ai/cli",
3
- "version": "1.5.0",
3
+ "version": "1.5.4",
4
4
  "description": "Elnora AI Platform CLI",
5
5
  "type": "module",
6
6
  "bin": {