@xmemo/client 0.4.138 → 0.4.139

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 (3) hide show
  1. package/README.md +7 -0
  2. package/package.json +1 -1
  3. package/src/cli.js +184 -4
package/README.md CHANGED
@@ -310,6 +310,11 @@ absence of embedded token values.
310
310
 
311
311
  ### Cursor
312
312
 
313
+ Cursor marketplace plugin assets live in `.cursor-plugin/marketplace.json` and
314
+ `plugins/xmemo/`. The marketplace plugin is OAuth-first and its `mcp.json` stores
315
+ only `https://xmemo.dev/mcp`; it must not contain `Authorization`, `Bearer`, or
316
+ `XMEMO_KEY`.
317
+
313
318
  Recommended Cursor setup:
314
319
 
315
320
  ```bash
@@ -331,6 +336,8 @@ Cursor configs include
331
336
  non-secret and stored under the user's XMemo CLI config directory. By default,
332
337
  the setup prompt also installs a Cursor behavior profile at
333
338
  `~/.cursor/memory-profile.md`; answer `n` or pass `--no-profile` to skip it.
339
+ Use this direct-key setup only for local/manual installs where Cursor OAuth is
340
+ unavailable; public plugin submission should use the OAuth-first plugin config.
334
341
 
335
342
  ### Gemini CLI
336
343
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xmemo/client",
3
- "version": "0.4.138",
3
+ "version": "0.4.139",
4
4
  "description": "Privacy-first CLI and MCP setup helper for XMemo.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -10,7 +10,7 @@ const PACKAGE_NAME = '@xmemo/client';
10
10
  const FALLBACK_PACKAGE_NAME = '@yonro/xmemo-client';
11
11
  const COMMAND_NAME = 'xmemo';
12
12
  const LEGACY_COMMAND_NAME = 'memory-os';
13
- const CLI_VERSION = '0.4.138';
13
+ const CLI_VERSION = '0.4.139';
14
14
  const DEFAULT_SERVICE_URL = 'https://xmemo.dev';
15
15
  const TOKEN_ENV_VAR = 'XMEMO_KEY';
16
16
  const LEGACY_TOKEN_ENV_VAR = 'MEMORY_OS_MCP_TOKEN';
@@ -64,6 +64,27 @@ const MCP_CLIENTS = new Map([
64
64
  buildSnippet: antigravityJsonSnippet,
65
65
  writeConfig: mergeAntigravityMcpConfig,
66
66
  configKind: 'json'
67
+ }],
68
+ ['antigravity-ide', {
69
+ label: 'Antigravity IDE',
70
+ defaultConfigPath: defaultAntigravityIdeConfigPath,
71
+ buildSnippet: antigravityIdeJsonSnippet,
72
+ writeConfig: mergeAntigravityIdeMcpConfig,
73
+ configKind: 'json'
74
+ }],
75
+ ['antigravity2', {
76
+ label: 'Antigravity 2.0',
77
+ defaultConfigPath: defaultAntigravity2ConfigPath,
78
+ buildSnippet: antigravity2JsonSnippet,
79
+ writeConfig: mergeAntigravity2McpConfig,
80
+ configKind: 'json'
81
+ }],
82
+ ['antigravity-cli', {
83
+ label: 'Antigravity CLI',
84
+ defaultConfigPath: defaultAntigravityCliConfigPath,
85
+ buildSnippet: antigravityCliJsonSnippet,
86
+ writeConfig: mergeAntigravityCliMcpConfig,
87
+ configKind: 'json'
67
88
  }]
68
89
  ]);
69
90
 
@@ -74,7 +95,10 @@ const SETUP_CLIENT_ALIASES = new Map([
74
95
  ['copilot-cli', 'copilot-cli'],
75
96
  ['gemini', 'gemini-cli'],
76
97
  ['gemini-cli', 'gemini-cli'],
77
- ['antigravity', 'antigravity']
98
+ ['antigravity', 'antigravity'],
99
+ ['antigravity-ide', 'antigravity-ide'],
100
+ ['antigravity2', 'antigravity2'],
101
+ ['antigravity-cli', 'antigravity-cli']
78
102
  ]);
79
103
 
80
104
  class UsageError extends Error {
@@ -1418,6 +1442,18 @@ function mcpConfigTemplate(clientId, mcpUrl) {
1418
1442
  return oauthJsonMcpTemplate(clientId, mcpUrl, antigravityJsonConfig(mcpUrl));
1419
1443
  }
1420
1444
 
1445
+ if (clientId === 'antigravity-ide') {
1446
+ return oauthJsonMcpTemplate(clientId, mcpUrl, antigravityIdeJsonConfig(mcpUrl));
1447
+ }
1448
+
1449
+ if (clientId === 'antigravity2') {
1450
+ return oauthJsonMcpTemplate(clientId, mcpUrl, antigravity2JsonConfig(mcpUrl));
1451
+ }
1452
+
1453
+ if (clientId === 'antigravity-cli') {
1454
+ return oauthJsonMcpTemplate(clientId, mcpUrl, antigravityCliJsonConfig(mcpUrl));
1455
+ }
1456
+
1421
1457
  return {
1422
1458
  client: clientId,
1423
1459
  serverName: MCP_SERVER_NAME,
@@ -2329,6 +2365,135 @@ async function mergeAntigravityMcpConfig(configPath, mcpUrl, identity) {
2329
2365
  await bestEffortChmod(configPath, 0o600);
2330
2366
  }
2331
2367
 
2368
+ function antigravityIdeJsonServerConfig(mcpUrl) {
2369
+ return {
2370
+ type: 'http',
2371
+ url: mcpUrl
2372
+ };
2373
+ }
2374
+
2375
+ function antigravityIdeJsonConfig(mcpUrl) {
2376
+ return {
2377
+ mcpServers: {
2378
+ [MCP_SERVER_NAME]: antigravityIdeJsonServerConfig(mcpUrl)
2379
+ }
2380
+ };
2381
+ }
2382
+
2383
+ function antigravityIdeJsonSnippet(mcpUrl, identity = envReferenceIdentity('antigravity-ide')) {
2384
+ return `${JSON.stringify(antigravityIdeJsonConfig(mcpUrl), null, 2)}\n`;
2385
+ }
2386
+
2387
+ async function mergeAntigravityIdeMcpConfig(configPath, mcpUrl, identity) {
2388
+ const existing = await readTextIfExists(configPath);
2389
+ const parsed = existing.trim().length === 0 ? {} : parseJsonConfig(existing, configPath);
2390
+
2391
+ if (!isPlainObject(parsed)) {
2392
+ throw new UsageError(`MCP JSON config must be an object: ${configPath}`);
2393
+ }
2394
+
2395
+ if (!isPlainObject(parsed.mcpServers)) {
2396
+ parsed.mcpServers = {};
2397
+ }
2398
+
2399
+ const existingName = existingJsonMcpServerName(parsed.mcpServers);
2400
+ if (existingName) {
2401
+ throw new UsageError(`MCP config already contains mcpServers.${existingName}. Edit ${configPath} manually to avoid duplicate server definitions.`);
2402
+ }
2403
+
2404
+ parsed.mcpServers[MCP_SERVER_NAME] = antigravityIdeJsonServerConfig(mcpUrl);
2405
+ await fs.mkdir(path.dirname(configPath), { recursive: true, mode: 0o700 });
2406
+ await fs.writeFile(configPath, `${JSON.stringify(parsed, null, 2)}\n`, { mode: 0o600 });
2407
+ await bestEffortChmod(configPath, 0o600);
2408
+ }
2409
+
2410
+ function antigravity2JsonServerConfig(mcpUrl) {
2411
+ return {
2412
+ type: 'http',
2413
+ url: mcpUrl
2414
+ };
2415
+ }
2416
+
2417
+ function antigravity2JsonConfig(mcpUrl) {
2418
+ return {
2419
+ mcpServers: {
2420
+ [MCP_SERVER_NAME]: antigravity2JsonServerConfig(mcpUrl)
2421
+ }
2422
+ };
2423
+ }
2424
+
2425
+ function antigravity2JsonSnippet(mcpUrl, identity = envReferenceIdentity('antigravity2')) {
2426
+ return `${JSON.stringify(antigravity2JsonConfig(mcpUrl), null, 2)}\n`;
2427
+ }
2428
+
2429
+ async function mergeAntigravity2McpConfig(configPath, mcpUrl, identity) {
2430
+ const existing = await readTextIfExists(configPath);
2431
+ const parsed = existing.trim().length === 0 ? {} : parseJsonConfig(existing, configPath);
2432
+
2433
+ if (!isPlainObject(parsed)) {
2434
+ throw new UsageError(`MCP JSON config must be an object: ${configPath}`);
2435
+ }
2436
+
2437
+ if (!isPlainObject(parsed.mcpServers)) {
2438
+ parsed.mcpServers = {};
2439
+ }
2440
+
2441
+ const existingName = existingJsonMcpServerName(parsed.mcpServers);
2442
+ if (existingName) {
2443
+ throw new UsageError(`MCP config already contains mcpServers.${existingName}. Edit ${configPath} manually to avoid duplicate server definitions.`);
2444
+ }
2445
+
2446
+ parsed.mcpServers[MCP_SERVER_NAME] = antigravity2JsonServerConfig(mcpUrl);
2447
+ await fs.mkdir(path.dirname(configPath), { recursive: true, mode: 0o700 });
2448
+ await fs.writeFile(configPath, `${JSON.stringify(parsed, null, 2)}\n`, { mode: 0o600 });
2449
+ await bestEffortChmod(configPath, 0o600);
2450
+ }
2451
+
2452
+ function antigravityCliJsonServerConfig(mcpUrl, identity = envReferenceIdentity('antigravity-cli')) {
2453
+ return {
2454
+ httpUrl: mcpUrl,
2455
+ headers: {
2456
+ [AGENT_ID_HEADER]: identity.agentId,
2457
+ [AGENT_INSTANCE_HEADER]: identity.agentInstanceId
2458
+ }
2459
+ };
2460
+ }
2461
+
2462
+ function antigravityCliJsonConfig(mcpUrl, identity = envReferenceIdentity('antigravity-cli')) {
2463
+ return {
2464
+ mcpServers: {
2465
+ [MCP_SERVER_NAME]: antigravityCliJsonServerConfig(mcpUrl, identity)
2466
+ }
2467
+ };
2468
+ }
2469
+
2470
+ function antigravityCliJsonSnippet(mcpUrl, identity = envReferenceIdentity('antigravity-cli')) {
2471
+ return `${JSON.stringify(antigravityCliJsonConfig(mcpUrl, identity), null, 2)}\n`;
2472
+ }
2473
+
2474
+ async function mergeAntigravityCliMcpConfig(configPath, mcpUrl, identity) {
2475
+ const existing = await readTextIfExists(configPath);
2476
+ const parsed = existing.trim().length === 0 ? {} : parseJsonConfig(existing, configPath);
2477
+
2478
+ if (!isPlainObject(parsed)) {
2479
+ throw new UsageError(`MCP JSON config must be an object: ${configPath}`);
2480
+ }
2481
+
2482
+ if (!isPlainObject(parsed.mcpServers)) {
2483
+ parsed.mcpServers = {};
2484
+ }
2485
+
2486
+ const existingName = existingJsonMcpServerName(parsed.mcpServers);
2487
+ if (existingName) {
2488
+ throw new UsageError(`MCP config already contains mcpServers.${existingName}. Edit ${configPath} manually to avoid duplicate server definitions.`);
2489
+ }
2490
+
2491
+ parsed.mcpServers[MCP_SERVER_NAME] = antigravityCliJsonServerConfig(mcpUrl, identity);
2492
+ await fs.mkdir(path.dirname(configPath), { recursive: true, mode: 0o700 });
2493
+ await fs.writeFile(configPath, `${JSON.stringify(parsed, null, 2)}\n`, { mode: 0o600 });
2494
+ await bestEffortChmod(configPath, 0o600);
2495
+ }
2496
+
2332
2497
 
2333
2498
  async function mergeGeminiMcpConfig(configPath, mcpUrl, identity) {
2334
2499
  const existing = await readTextIfExists(configPath);
@@ -2485,11 +2650,11 @@ function supportedMcpClientIds() {
2485
2650
  }
2486
2651
 
2487
2652
  function supportedSetupClientIds() {
2488
- return ['codex', 'cursor', 'copilot', 'gemini', 'antigravity'];
2653
+ return ['codex', 'cursor', 'copilot', 'gemini', 'antigravity', 'antigravity-ide', 'antigravity2', 'antigravity-cli'];
2489
2654
  }
2490
2655
 
2491
2656
  function usesClientOAuth(clientId) {
2492
- return clientId === 'gemini-cli' || clientId === 'antigravity';
2657
+ return clientId === 'gemini-cli' || clientId === 'antigravity' || clientId === 'antigravity-ide' || clientId === 'antigravity2' || clientId === 'antigravity-cli';
2493
2658
  }
2494
2659
 
2495
2660
  function credentialsPath(env) {
@@ -2537,6 +2702,21 @@ function defaultAntigravityConfigPath(env) {
2537
2702
  return path.join(home, '.gemini', 'antigravity', 'mcp_config.json');
2538
2703
  }
2539
2704
 
2705
+ function defaultAntigravityIdeConfigPath(env) {
2706
+ const home = env.USERPROFILE || env.HOME || os.homedir();
2707
+ return path.join(home, '.antigravity-ide', 'mcp.json');
2708
+ }
2709
+
2710
+ function defaultAntigravity2ConfigPath(env) {
2711
+ const home = env.USERPROFILE || env.HOME || os.homedir();
2712
+ return path.join(home, '.antigravity2', 'mcp.json');
2713
+ }
2714
+
2715
+ function defaultAntigravityCliConfigPath(env) {
2716
+ const home = env.USERPROFILE || env.HOME || os.homedir();
2717
+ return path.join(home, '.antigravity', 'settings.json');
2718
+ }
2719
+
2540
2720
  function defaultCopilotConfigPath(env) {
2541
2721
  const home = env.USERPROFILE || env.HOME || os.homedir();
2542
2722
  return path.join(env.COPILOT_HOME ?? path.join(home, '.copilot'), 'mcp-config.json');