@xmemo/client 0.4.132 → 0.4.133
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/README.md +18 -10
- package/package.json +1 -1
- package/src/cli.js +84 -25
package/README.md
CHANGED
|
@@ -31,7 +31,9 @@ to print the exact command without changing anything.
|
|
|
31
31
|
xmemo update
|
|
32
32
|
xmemo setup codex
|
|
33
33
|
xmemo setup codex --yes
|
|
34
|
-
xmemo
|
|
34
|
+
xmemo setup cursor
|
|
35
|
+
xmemo setup cursor --yes
|
|
36
|
+
xmemo setup copilot
|
|
35
37
|
xmemo doctor
|
|
36
38
|
xmemo discovery show
|
|
37
39
|
xmemo setup
|
|
@@ -44,7 +46,7 @@ xmemo env example --shell bash
|
|
|
44
46
|
xmemo mcp list
|
|
45
47
|
xmemo mcp config --client generic
|
|
46
48
|
xmemo profile status codex
|
|
47
|
-
xmemo
|
|
49
|
+
xmemo smoke --client codex
|
|
48
50
|
xmemo privacy
|
|
49
51
|
```
|
|
50
52
|
|
|
@@ -142,12 +144,13 @@ Generate and write a client config from discovery:
|
|
|
142
144
|
```bash
|
|
143
145
|
xmemo setup codex --yes
|
|
144
146
|
xmemo setup codex --url "https://your-private-service.example" --yes
|
|
145
|
-
xmemo setup
|
|
146
|
-
xmemo setup
|
|
147
|
+
xmemo setup cursor --yes
|
|
148
|
+
xmemo setup copilot
|
|
147
149
|
```
|
|
148
150
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
+
`xmemo setup <client>` is the unified setup entry point. Without `--yes` it
|
|
152
|
+
previews what will happen. With `--yes`, write-capable clients apply the
|
|
153
|
+
user-scoped config. Generated config references `XMEMO_KEY`; it does not embed
|
|
151
154
|
the token value. Write-capable client configs also include stable non-secret
|
|
152
155
|
agent identity headers where the client format supports them.
|
|
153
156
|
|
|
@@ -192,7 +195,7 @@ directly. The recommended personal-user path is therefore local proxy mode:
|
|
|
192
195
|
|
|
193
196
|
```bash
|
|
194
197
|
xmemo login
|
|
195
|
-
xmemo
|
|
198
|
+
xmemo setup copilot
|
|
196
199
|
xmemo mcp proxy
|
|
197
200
|
```
|
|
198
201
|
|
|
@@ -200,6 +203,9 @@ The generated Copilot CLI template points at `http://127.0.0.1:8765/mcp` and
|
|
|
200
203
|
does not include token or identity headers. `xmemo mcp proxy` reads the token
|
|
201
204
|
saved by `xmemo login` or `xmemo token add --from-stdin`, adds the XMemo bearer
|
|
202
205
|
token and local agent identity, then forwards requests to `https://xmemo.dev/mcp`.
|
|
206
|
+
Copilot CLI does not currently document a stable cross-platform config file for
|
|
207
|
+
third-party tools to edit, so `xmemo setup copilot` prints the template and next
|
|
208
|
+
command instead of writing directly.
|
|
203
209
|
If you specifically want the older environment-variable template, run:
|
|
204
210
|
|
|
205
211
|
```bash
|
|
@@ -267,13 +273,15 @@ absence of embedded token values.
|
|
|
267
273
|
|
|
268
274
|
### Cursor
|
|
269
275
|
|
|
270
|
-
|
|
276
|
+
Recommended Cursor setup:
|
|
271
277
|
|
|
272
278
|
```bash
|
|
273
|
-
xmemo
|
|
279
|
+
xmemo setup cursor
|
|
280
|
+
xmemo setup cursor --yes
|
|
274
281
|
```
|
|
275
282
|
|
|
276
|
-
|
|
283
|
+
`setup cursor` previews the Cursor MCP config. `setup cursor --yes` merges it
|
|
284
|
+
into the default Cursor user config path. The lower-level equivalent remains:
|
|
277
285
|
|
|
278
286
|
```bash
|
|
279
287
|
xmemo mcp add cursor --url "$XMEMO_URL" --write
|
package/package.json
CHANGED
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.
|
|
13
|
+
const CLI_VERSION = '0.4.133';
|
|
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';
|
|
@@ -44,6 +44,13 @@ const MCP_CLIENTS = new Map([
|
|
|
44
44
|
}]
|
|
45
45
|
]);
|
|
46
46
|
|
|
47
|
+
const SETUP_CLIENT_ALIASES = new Map([
|
|
48
|
+
['codex', 'codex'],
|
|
49
|
+
['cursor', 'cursor'],
|
|
50
|
+
['copilot', 'copilot-cli'],
|
|
51
|
+
['copilot-cli', 'copilot-cli']
|
|
52
|
+
]);
|
|
53
|
+
|
|
47
54
|
class UsageError extends Error {
|
|
48
55
|
constructor(message) {
|
|
49
56
|
super(message);
|
|
@@ -150,7 +157,7 @@ function writeHelp(io) {
|
|
|
150
157
|
writeLine(io.stdout, ` ${COMMAND_NAME} update [--dry-run] [--json]`);
|
|
151
158
|
writeLine(io.stdout, ` ${COMMAND_NAME} doctor [--base-url <https://api.example.com>] [--json]`);
|
|
152
159
|
writeLine(io.stdout, ` ${COMMAND_NAME} discovery show [--base-url <https://api.example.com>] [--json]`);
|
|
153
|
-
writeLine(io.stdout, ` ${COMMAND_NAME} setup
|
|
160
|
+
writeLine(io.stdout, ` ${COMMAND_NAME} setup <codex|cursor|copilot> [--url <https://api.example.com>] [--write|--yes] [--json]`);
|
|
154
161
|
writeLine(io.stdout, ` ${COMMAND_NAME} login [--from-stdin] [--base-url <url>] [--timeout-ms <ms>] [--http-timeout-ms <ms>] [--json]`);
|
|
155
162
|
writeLine(io.stdout, ` ${COMMAND_NAME} auth status [--verify] [--base-url <url>] [--json]`);
|
|
156
163
|
writeLine(io.stdout, ` ${COMMAND_NAME} status [--url <https://api.example.com>] [--json]`);
|
|
@@ -361,7 +368,7 @@ async function setupCommand(args, io) {
|
|
|
361
368
|
const outputJson = hasFlag(optionArgs, '--json');
|
|
362
369
|
const shortClientSetup = Boolean(positionalClientId);
|
|
363
370
|
const writeConfig = hasFlag(optionArgs, '--write') || (shortClientSetup && hasFlag(optionArgs, '--yes'));
|
|
364
|
-
const clientId = positionalClientId ?? optionValue(optionArgs, '--client');
|
|
371
|
+
const clientId = normalizeSetupClientId(positionalClientId ?? optionValue(optionArgs, '--client'));
|
|
365
372
|
const timeoutMs = parsePositiveInteger(optionValue(optionArgs, '--timeout-ms') ?? '5000', '--timeout-ms');
|
|
366
373
|
const installProfile = shortClientSetup
|
|
367
374
|
&& clientId === 'codex'
|
|
@@ -383,24 +390,32 @@ async function setupCommand(args, io) {
|
|
|
383
390
|
const setupPlan = buildSetupPlan({ baseUrl, discoveryUrl, statusUrl, discovery, status });
|
|
384
391
|
|
|
385
392
|
if (clientId) {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
393
|
+
if (clientId === 'copilot-cli') {
|
|
394
|
+
if (writeConfig) {
|
|
395
|
+
throw new UsageError(`Copilot CLI setup cannot be written automatically yet. Run \`${COMMAND_NAME} setup copilot\` to print the local proxy template, then add it with Copilot CLI MCP management.`);
|
|
396
|
+
}
|
|
397
|
+
const proxyPort = parsePositiveInteger(optionValue(optionArgs, '--port') ?? String(DEFAULT_PROXY_PORT), '--port');
|
|
398
|
+
setupPlan.selectedClient = copilotSetupPlan(setupPlan.mcpUrl, proxyPort);
|
|
399
|
+
} else {
|
|
400
|
+
const client = MCP_CLIENTS.get(clientId);
|
|
401
|
+
if (!client) {
|
|
402
|
+
throw new UsageError(`Unsupported MCP client: ${clientId}. Supported clients: ${supportedSetupClientIds().join(', ')}.`);
|
|
403
|
+
}
|
|
390
404
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
405
|
+
const identity = writeConfig ? await agentIdentity(clientId, io.env) : envReferenceIdentity(clientId);
|
|
406
|
+
setupPlan.selectedClient = clientSetupPlan(clientId, client, setupPlan.mcpUrl, io.env, identity);
|
|
407
|
+
if (writeConfig) {
|
|
408
|
+
await client.writeConfig(setupPlan.selectedClient.configPath, setupPlan.mcpUrl, identity);
|
|
409
|
+
setupPlan.selectedClient.written = true;
|
|
410
|
+
}
|
|
397
411
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
412
|
+
if (clientId === 'codex' && shortClientSetup) {
|
|
413
|
+
const profileTarget = optionValue(optionArgs, '--profile-target')
|
|
414
|
+
?? optionValue(optionArgs, '--target')
|
|
415
|
+
?? defaultCodexProfileTarget();
|
|
416
|
+
const profileResult = await codexProfileInstallResult(profileTarget, { write: installProfile });
|
|
417
|
+
setupPlan.selectedClient.codexProfile = profileResult;
|
|
418
|
+
}
|
|
404
419
|
}
|
|
405
420
|
}
|
|
406
421
|
|
|
@@ -1410,6 +1425,28 @@ function clientSetupPlan(clientId, client, mcpUrl, env, identity) {
|
|
|
1410
1425
|
};
|
|
1411
1426
|
}
|
|
1412
1427
|
|
|
1428
|
+
function copilotSetupPlan(mcpUrl, proxyPort) {
|
|
1429
|
+
const proxyUrl = `http://${DEFAULT_PROXY_HOST}:${proxyPort}/mcp`;
|
|
1430
|
+
const template = mcpLocalProxyTemplate('copilot-cli', proxyUrl);
|
|
1431
|
+
return {
|
|
1432
|
+
id: 'copilot-cli',
|
|
1433
|
+
label: 'Copilot CLI',
|
|
1434
|
+
configKind: 'local-proxy',
|
|
1435
|
+
configPath: 'Copilot CLI MCP config',
|
|
1436
|
+
serverName: template.serverName,
|
|
1437
|
+
mcpUrl,
|
|
1438
|
+
proxyUrl,
|
|
1439
|
+
tokenEnvVar: TOKEN_ENV_VAR,
|
|
1440
|
+
requiresCredential: template.requiresCredential,
|
|
1441
|
+
requiresLocalCommand: template.requiresLocalCommand,
|
|
1442
|
+
template: template.snippet,
|
|
1443
|
+
agentId: template.agentIdentity.agentId,
|
|
1444
|
+
writesTokenValue: false,
|
|
1445
|
+
writeSupported: false,
|
|
1446
|
+
written: false
|
|
1447
|
+
};
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1413
1450
|
function writeSetupSummary(plan, io) {
|
|
1414
1451
|
writeLine(io.stdout, `${PRODUCT_NAME} setup discovery: ${plan.baseUrl}`);
|
|
1415
1452
|
writeLine(io.stdout, ` API: ${plan.apiBase}`);
|
|
@@ -1436,7 +1473,16 @@ function writeSetupSummary(plan, io) {
|
|
|
1436
1473
|
writeLine(io.stdout, ` Written: ${plan.selectedClient.written}`);
|
|
1437
1474
|
writeLine(io.stdout, ` Token value embedded: ${plan.selectedClient.writesTokenValue}`);
|
|
1438
1475
|
writeLine(io.stdout, ` Agent ID: ${plan.selectedClient.agentId}`);
|
|
1439
|
-
|
|
1476
|
+
if (plan.selectedClient.agentInstanceIdPath) {
|
|
1477
|
+
writeLine(io.stdout, ` Agent instance ID stored: ${plan.selectedClient.agentInstanceIdPath}`);
|
|
1478
|
+
}
|
|
1479
|
+
if (plan.selectedClient.configKind === 'local-proxy') {
|
|
1480
|
+
writeLine(io.stdout, ` Local proxy: ${plan.selectedClient.requiresLocalCommand}`);
|
|
1481
|
+
writeLine(io.stdout, ' MCP template:');
|
|
1482
|
+
writeLine(io.stdout, JSON.stringify(plan.selectedClient.template, null, 2));
|
|
1483
|
+
writeLine(io.stdout, ` Next: add the template with Copilot CLI MCP management, then keep \`${plan.selectedClient.requiresLocalCommand}\` running while you use Copilot CLI.`);
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1440
1486
|
if (plan.selectedClient.codexProfile) {
|
|
1441
1487
|
const profile = plan.selectedClient.codexProfile;
|
|
1442
1488
|
writeLine(io.stdout, ` Codex profile target: ${profile.targetPath}`);
|
|
@@ -1447,7 +1493,7 @@ function writeSetupSummary(plan, io) {
|
|
|
1447
1493
|
}
|
|
1448
1494
|
}
|
|
1449
1495
|
if (!plan.selectedClient.written) {
|
|
1450
|
-
writeLine(io.stdout, ` Next: ${COMMAND_NAME}
|
|
1496
|
+
writeLine(io.stdout, ` Next: ${COMMAND_NAME} setup ${plan.selectedClient.id} --url ${plan.baseUrl} --yes`);
|
|
1451
1497
|
}
|
|
1452
1498
|
return;
|
|
1453
1499
|
}
|
|
@@ -1455,7 +1501,7 @@ function writeSetupSummary(plan, io) {
|
|
|
1455
1501
|
writeLine(io.stdout, '');
|
|
1456
1502
|
writeLine(io.stdout, 'Next steps:');
|
|
1457
1503
|
writeLine(io.stdout, ` 1. Create a scoped token in the token portal and store it in ${plan.tokenEnvVar}.`);
|
|
1458
|
-
writeLine(io.stdout, ` 2. Configure a client, for example: ${COMMAND_NAME} setup --url ${plan.baseUrl} --
|
|
1504
|
+
writeLine(io.stdout, ` 2. Configure a client, for example: ${COMMAND_NAME} setup codex --url ${plan.baseUrl} --yes`);
|
|
1459
1505
|
writeLine(io.stdout, ` 3. Run ${COMMAND_NAME} status to smoke-test the service without sending the token.`);
|
|
1460
1506
|
}
|
|
1461
1507
|
|
|
@@ -1904,6 +1950,10 @@ function supportedMcpClientIds() {
|
|
|
1904
1950
|
return Array.from(MCP_CLIENTS.keys());
|
|
1905
1951
|
}
|
|
1906
1952
|
|
|
1953
|
+
function supportedSetupClientIds() {
|
|
1954
|
+
return ['codex', 'cursor', 'copilot'];
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1907
1957
|
function credentialsPath(env) {
|
|
1908
1958
|
return path.join(configRoot(env), 'credentials.json');
|
|
1909
1959
|
}
|
|
@@ -1990,11 +2040,20 @@ function positionalClientArg(args) {
|
|
|
1990
2040
|
return null;
|
|
1991
2041
|
}
|
|
1992
2042
|
|
|
1993
|
-
|
|
1994
|
-
|
|
2043
|
+
return normalizeSetupClientId(candidate);
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2046
|
+
function normalizeSetupClientId(candidate) {
|
|
2047
|
+
if (!candidate) {
|
|
2048
|
+
return null;
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
const normalized = SETUP_CLIENT_ALIASES.get(candidate);
|
|
2052
|
+
if (!normalized) {
|
|
2053
|
+
throw new UsageError(`Unsupported setup client: ${candidate}. Supported clients: ${supportedSetupClientIds().join(', ')}.`);
|
|
1995
2054
|
}
|
|
1996
2055
|
|
|
1997
|
-
return
|
|
2056
|
+
return normalized;
|
|
1998
2057
|
}
|
|
1999
2058
|
|
|
2000
2059
|
function optionValue(args, name) {
|