@memorax/memorax-code 0.1.4 → 0.1.6

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 (87) hide show
  1. package/README.md +8 -19
  2. package/bin/memorax-code-npm-preinstall.mjs +28 -39
  3. package/bin/memorax-code-plugin-postinstall.mjs +23 -1537
  4. package/bin/memorax-code-setup.mjs +1615 -0
  5. package/bin/memorax-code.mjs +289 -5
  6. package/docs/configuration.md +66 -17
  7. package/docs/troubleshooting.md +105 -7
  8. package/lib/memorax-code-adapter-common/src/config-utils.d.mts +5 -1
  9. package/lib/memorax-code-adapter-common/src/config-utils.mjs +36 -3
  10. package/lib/memorax-code-adapter-common/src/credentials/linux-secret-service.mjs +110 -0
  11. package/lib/memorax-code-adapter-common/src/credentials/macos-keychain.mjs +224 -0
  12. package/lib/memorax-code-adapter-common/src/credentials/secure-command.mjs +340 -0
  13. package/lib/memorax-code-adapter-common/src/credentials/trial-credential-record.d.mts +82 -0
  14. package/lib/memorax-code-adapter-common/src/credentials/trial-credential-record.mjs +183 -0
  15. package/lib/memorax-code-adapter-common/src/credentials/trial-credential-store.d.mts +82 -0
  16. package/lib/memorax-code-adapter-common/src/credentials/trial-credential-store.mjs +271 -0
  17. package/lib/memorax-code-adapter-common/src/credentials/windows-dpapi.mjs +440 -0
  18. package/lib/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +7 -4
  19. package/lib/memorax-code-adapter-common/src/setup-completion.d.mts +81 -0
  20. package/lib/memorax-code-adapter-common/src/setup-completion.mjs +154 -0
  21. package/lib/memorax-code-backend/dist/clients/claude/memory-hook-runtime.js +21 -2
  22. package/lib/memorax-code-backend/dist/clients/codex/memory-hook-runtime.js +23 -3
  23. package/lib/memorax-code-backend/dist/clients/opencode/memory-hook-runtime.js +19 -1
  24. package/lib/memorax-code-backend/dist/entrypoints/backend-cli.js +17 -16
  25. package/lib/memorax-code-backend/dist/lifecycle/backend/process.js +21 -0
  26. package/lib/memorax-code-backend/dist/lifecycle/orchestrator.js +81 -22
  27. package/lib/memorax-code-backend/dist/memorax-cli.js +3 -0
  28. package/lib/memorax-code-backend/dist/memory/automatic-retrieval.js +8 -2
  29. package/lib/memorax-code-backend/dist/memory/automatic-writeback.js +13 -1
  30. package/lib/memorax-code-backend/dist/memory/cli.js +10 -0
  31. package/lib/memorax-code-backend/dist/memory/quota-notice.js +208 -0
  32. package/lib/memorax-code-backend/dist/memory/service.js +11 -0
  33. package/lib/memorax-code-backend/dist/provider/memorax/adapter.js +4 -2
  34. package/lib/memorax-code-backend/dist/provider/memorax/http.js +10 -3
  35. package/lib/memorax-code-backend/dist/provider/memorax/quota.js +26 -0
  36. package/lib/memorax-code-backend/package.json +2 -2
  37. package/lib/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
  38. package/lib/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
  39. package/lib/memorax-code-claude-adapter/package.json +1 -1
  40. package/lib/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +5 -3
  41. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +2 -0
  42. package/lib/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +4 -2
  43. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/.claude-plugin/plugin.json +1 -1
  44. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/hooks/runtime-shell.json +1 -1
  45. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/config-utils.d.mts +5 -1
  46. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/config-utils.mjs +36 -3
  47. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/credentials/linux-secret-service.mjs +110 -0
  48. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/credentials/macos-keychain.mjs +224 -0
  49. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/credentials/secure-command.mjs +340 -0
  50. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/credentials/trial-credential-record.d.mts +82 -0
  51. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/credentials/trial-credential-record.mjs +183 -0
  52. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/credentials/trial-credential-store.d.mts +82 -0
  53. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/credentials/trial-credential-store.mjs +271 -0
  54. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/credentials/windows-dpapi.mjs +440 -0
  55. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/hooks/memory-skill-reminder-hook.mjs +7 -4
  56. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/setup-completion.d.mts +81 -0
  57. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/memorax-code-adapter-common/src/setup-completion.mjs +154 -0
  58. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/package.json +1 -1
  59. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/runtime-hooks/memory-turn.mjs +5 -3
  60. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-add.md +2 -0
  61. package/lib/memorax-code-claude-marketplace/plugins/memorax-code-claude-adapter/skills/memorax-code/references/memorax-search.md +4 -2
  62. package/lib/memorax-code-codex-adapter/.codex-plugin/plugin.json +1 -1
  63. package/lib/memorax-code-codex-adapter/hooks/runtime-shell.json +1 -1
  64. package/lib/memorax-code-codex-adapter/package.json +1 -1
  65. package/lib/memorax-code-codex-adapter/runtime-hooks/memory-skill-reminder.mjs +2 -0
  66. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-add.md +2 -0
  67. package/lib/memorax-code-codex-adapter/skills/memorax-code/references/memorax-search.md +4 -2
  68. package/lib/memorax-code-dsh-adapter/hooks/repo-memory-job.mjs +5 -2
  69. package/lib/memorax-code-dsh-adapter/package.json +1 -1
  70. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/memorax-add.md +2 -0
  71. package/lib/memorax-code-dsh-adapter/skills/memorax-code/references/memorax-search.md +4 -2
  72. package/lib/memorax-code-dsh-adapter/src/profile-lifecycle.mjs +158 -7
  73. package/lib/memorax-code-dsh-adapter/src/runtime-state.mjs +21 -0
  74. package/lib/memorax-code-opencode-adapter/package.json +1 -1
  75. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/memorax-add.md +2 -0
  76. package/lib/memorax-code-opencode-adapter/skills/memorax-code/references/memorax-search.md +4 -2
  77. package/lib/memorax-code-opencode-adapter/src/plugin.mjs +20 -0
  78. package/lib/node-version.mjs +1 -1
  79. package/lib/package-transition.mjs +311 -0
  80. package/lib/resolve-codex-command.mjs +32 -6
  81. package/lib/setup-memory-preferences.mjs +113 -0
  82. package/lib/setup-reconcile.mjs +128 -0
  83. package/lib/trial-plugin-mark.mjs +171 -0
  84. package/lib/trial-provision-client.mjs +307 -0
  85. package/lib/trial-provision-flow.mjs +215 -0
  86. package/lib/trial-setup.mjs +53 -0
  87. package/package.json +2 -2
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import { spawn } from "node:child_process";
2
+ import { spawn, spawnSync } from "node:child_process";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import { homedir } from "node:os";
5
5
  import { dirname, join, resolve } from "node:path";
6
- import { fileURLToPath } from "node:url";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
7
  import { stagePackagedClientHookRuntime } from "../lib/client-hook-runtime.mjs";
8
8
  import { unsupportedNodeVersionMessage } from "../lib/node-version.mjs";
9
9
  import { resolveNpmInvocation } from "../lib/npm-invocation.mjs";
@@ -37,6 +37,51 @@ Options:
37
37
  -h, --help Show this help message`);
38
38
  }
39
39
 
40
+ function printMainHelp() {
41
+ console.log(`Usage: memorax-code [command] [options]
42
+
43
+ Commands:
44
+ setup Run or repair the interactive setup
45
+ account Manage local MemoraX account information
46
+ start Reconcile selected integrations and start the Backend
47
+ status Show Backend and integration status
48
+ stop Stop the Backend and selected integrations
49
+ restart Restart the Backend and selected integrations
50
+ update Update the globally installed npm package
51
+ uninstall Remove managed integrations and the npm package
52
+ logs Show Backend logs
53
+ token Manage the local Backend token
54
+
55
+ Run \`memorax-code setup\` to complete first-time setup or repair an installation.
56
+ Run \`memorax-code\` with no command to show setup guidance or current status.
57
+ Run \`memorax-code <command> --help\` for command-specific options.`);
58
+ }
59
+
60
+ function printAccountHelp() {
61
+ console.log(`Usage: memorax-code account --show-mark-id [--home DIR]
62
+
63
+ Show the Mark ID for the ready local trial identity. Run this command directly
64
+ in your local terminal and keep its output private.
65
+
66
+ Options:
67
+ --show-mark-id Show the complete local trial Mark ID
68
+ --home DIR Read the specified MemoraX Code home
69
+ -h, --help Show this help message`);
70
+ }
71
+
72
+ function printSetupHelp() {
73
+ console.log(`Usage: memorax-code setup [--existing-account | --reconfigure] [--home DIR]
74
+
75
+ Run interactive setup to configure or repair MemoraX Code. A complete existing
76
+ configuration is reused automatically.
77
+
78
+ Options:
79
+ --existing-account Configure an existing account instead of anonymous access
80
+ --reconfigure Re-detect memory preferences instead of reusing configuration
81
+ --home DIR Configure the specified MemoraX Code home
82
+ -h, --help Show this help message`);
83
+ }
84
+
40
85
  function printCommand(command, args) {
41
86
  console.log([command, ...args].join(" "));
42
87
  }
@@ -48,6 +93,39 @@ function npmCommandCwd() {
48
93
  return "/";
49
94
  }
50
95
 
96
+ async function runAccountCommand(args) {
97
+ if (args.includes("--help") || args.includes("-h")) {
98
+ printAccountHelp();
99
+ return 0;
100
+ }
101
+ let memoraxCodeHome;
102
+ try {
103
+ memoraxCodeHome = requestedMemoraxCodeHome(args);
104
+ assertAccountArgs(args);
105
+ } catch (error) {
106
+ console.error(`memorax-code account: ${error instanceof Error ? error.message : String(error)}`);
107
+ printAccountHelp();
108
+ return 2;
109
+ }
110
+
111
+ try {
112
+ const { loadReadyTrialSetupCredential } = await loadTrialSetupApi();
113
+ const credential = await loadReadyTrialSetupCredential({
114
+ memoraxCodeHome,
115
+ env: process.env,
116
+ });
117
+ if (!credential) {
118
+ console.error("memorax-code account: no ready local trial identity was found");
119
+ return 1;
120
+ }
121
+ console.log(`Mark ID: ${credential.markId}`);
122
+ return 0;
123
+ } catch {
124
+ console.error("memorax-code account: unable to read the secure local trial identity");
125
+ return 1;
126
+ }
127
+ }
128
+
51
129
  async function runUpdateCommand(args) {
52
130
  let dryRun = false;
53
131
  let force = false;
@@ -98,7 +176,6 @@ async function runUpdateCommand(args) {
98
176
  const channel = requestedChannel ?? (pkg.version.includes("-") ? "preview" : "latest");
99
177
  const npmArgs = ["install", "-g", `${pkg.name}@${channel}`];
100
178
  if (force) npmArgs.push("--force");
101
- npmArgs.push("--foreground-scripts");
102
179
 
103
180
  if (dryRun) {
104
181
  printCommand("npm", npmArgs);
@@ -120,11 +197,10 @@ async function runUpdateCommand(args) {
120
197
  env: {
121
198
  ...process.env,
122
199
  PWD: cwd,
123
- MEMORAX_CODE_NPM_POSTINSTALL_UPDATE: "1",
124
200
  ...(requestedHome ? { MEMORAX_CODE_HOME: requestedHome } : {}),
125
201
  },
126
202
  });
127
- return await new Promise((resolve) => {
203
+ const npmExitCode = await new Promise((resolve) => {
128
204
  child.on("error", (error) => {
129
205
  console.error(`memorax-code update: failed to start npm: ${error.message}`);
130
206
  resolve(1);
@@ -138,6 +214,196 @@ async function runUpdateCommand(args) {
138
214
  }
139
215
  });
140
216
  });
217
+ if (npmExitCode !== 0) return npmExitCode;
218
+
219
+ const memoraxCodeHome = requestedHome ?? requestedMemoraxCodeHome([]);
220
+ if (!existsSync(join(memoraxCodeHome, "runtime", "backend", "backend.pid.json"))) {
221
+ console.error("memorax-code update: package updated; the managed Backend remains stopped; run `memorax-code setup` from a terminal to review client and Hook changes");
222
+ return 0;
223
+ }
224
+ if (!setupCanPrompt()) {
225
+ console.error("memorax-code update: package updated; run `memorax-code setup` from a terminal to review client and Hook changes");
226
+ return 0;
227
+ }
228
+ return await runSetupCommand(["--home", memoraxCodeHome], { updateMode: true });
229
+ }
230
+
231
+ async function runSetupCommand(args, { updateMode = false } = {}) {
232
+ if (args.includes("--help") || args.includes("-h")) {
233
+ printSetupHelp();
234
+ return 0;
235
+ }
236
+ let memoraxCodeHome;
237
+ let setupMode;
238
+ try {
239
+ memoraxCodeHome = requestedMemoraxCodeHome(args);
240
+ setupMode = parseSetupMode(args);
241
+ } catch (error) {
242
+ console.error(`memorax-code setup: ${error instanceof Error ? error.message : String(error)}`);
243
+ printSetupHelp();
244
+ return 2;
245
+ }
246
+ if (!setupCanPrompt()) {
247
+ console.error("memorax-code setup: an interactive terminal is required");
248
+ return 1;
249
+ }
250
+ try {
251
+ const { withSetupCompletionLock } = await loadSetupCompletionApi();
252
+ return await withSetupCompletionLock(memoraxCodeHome, async (completion) => {
253
+ if (updateMode && completion.status === "absent") {
254
+ if (hasReadyMemoraxConfiguration(memoraxCodeHome)) {
255
+ console.error("memorax-code update: existing configuration detected; completing the one-time setup migration");
256
+ return await spawnSetupProcess(memoraxCodeHome, { setupMode });
257
+ }
258
+ console.error("memorax-code update: package updated; setup has not been completed; run `memorax-code setup` from an interactive terminal");
259
+ return 0;
260
+ }
261
+ if (updateMode) {
262
+ console.error("memorax-code update: reviewing client and Hook changes in the foreground");
263
+ }
264
+ return await spawnSetupProcess(memoraxCodeHome, {
265
+ updateMode,
266
+ setupMode,
267
+ });
268
+ });
269
+ } catch (error) {
270
+ console.error(`memorax-code setup: ${error instanceof Error ? error.message : String(error)}`);
271
+ return 1;
272
+ }
273
+ }
274
+
275
+ async function routeDefaultCommand() {
276
+ const memoraxCodeHome = requestedMemoraxCodeHome([]);
277
+ try {
278
+ const { readSetupCompletionRecord, setupCompletionPath } = await loadSetupCompletionApi();
279
+ const state = readSetupCompletionRecord(memoraxCodeHome);
280
+ if (state.status === "absent") {
281
+ if (setupCanPrompt() && hasReadyMemoraxConfiguration(memoraxCodeHome)) {
282
+ console.error("memorax-code: existing configuration detected; completing the one-time setup migration");
283
+ return await runSetupCommand(["--home", memoraxCodeHome]);
284
+ }
285
+ console.error("memorax-code: setup has not been completed. Run `memorax-code setup` from an interactive terminal.");
286
+ return 1;
287
+ }
288
+ if (state.status !== "valid") {
289
+ const detail = state.status === "unsupported"
290
+ ? `uses unsupported version ${state.version}`
291
+ : `is invalid (${state.reason})`;
292
+ console.error(`memorax-code: setup completion record ${detail}: ${setupCompletionPath(memoraxCodeHome)}`);
293
+ console.error("Inspect or repair this private record before running setup again.");
294
+ return 1;
295
+ }
296
+ process.argv.splice(2, 0, "status");
297
+ return undefined;
298
+ } catch (error) {
299
+ console.error(`memorax-code: unable to inspect setup state: ${error instanceof Error ? error.message : String(error)}`);
300
+ return 1;
301
+ }
302
+ }
303
+
304
+ function assertAccountArgs(args) {
305
+ let showMarkId = false;
306
+ for (let index = 0; index < args.length; index += 1) {
307
+ const arg = args[index];
308
+ if (arg === "--show-mark-id") {
309
+ showMarkId = true;
310
+ } else if (arg === "--home") {
311
+ const value = args[++index];
312
+ if (!value || value.startsWith("--")) throw new Error("--home requires a directory");
313
+ } else if (arg.startsWith("--home=")) {
314
+ if (!arg.slice("--home=".length).trim()) throw new Error("--home requires a directory");
315
+ } else {
316
+ throw new Error(`unknown option ${arg}`);
317
+ }
318
+ }
319
+ if (!showMarkId) throw new Error("--show-mark-id is required");
320
+ }
321
+
322
+ function parseSetupMode(args) {
323
+ let setupMode = "automatic";
324
+ for (let index = 0; index < args.length; index += 1) {
325
+ const arg = args[index];
326
+ if (arg === "--existing-account" || arg === "--reconfigure") {
327
+ const requestedMode = arg === "--existing-account" ? "existing-account" : "reconfigure";
328
+ if (setupMode !== "automatic" && setupMode !== requestedMode) {
329
+ throw new Error("--existing-account and --reconfigure cannot be used together");
330
+ }
331
+ setupMode = requestedMode;
332
+ } else if (arg === "--home") {
333
+ const value = args[++index];
334
+ if (!value || value.startsWith("--")) throw new Error("--home requires a directory");
335
+ } else if (arg.startsWith("--home=")) {
336
+ if (!arg.slice("--home=".length).trim()) throw new Error("--home requires a directory");
337
+ } else {
338
+ throw new Error(`unknown option ${arg}`);
339
+ }
340
+ }
341
+ return setupMode;
342
+ }
343
+
344
+ function setupCanPrompt() {
345
+ return truthyEnv(process.env.MEMORAX_CODE_SETUP_ASSUME_INTERACTIVE)
346
+ || (process.stdin.isTTY === true && process.stderr.isTTY === true);
347
+ }
348
+
349
+ async function loadSetupCompletionApi() {
350
+ const modulePath = join(
351
+ packageRoot(),
352
+ "lib",
353
+ "memorax-code-adapter-common",
354
+ "src",
355
+ "setup-completion.mjs",
356
+ );
357
+ return await import(pathToFileURL(modulePath).href);
358
+ }
359
+
360
+ async function loadTrialSetupApi() {
361
+ return await import(pathToFileURL(join(packageRoot(), "lib", "trial-setup.mjs")).href);
362
+ }
363
+
364
+ function hasReadyMemoraxConfiguration(memoraxCodeHome) {
365
+ const result = spawnSync(process.execPath, [
366
+ join(packageRoot(), "bin", "memorax-cli.mjs"),
367
+ "status",
368
+ "--json",
369
+ "--config-only",
370
+ ], {
371
+ encoding: "utf8",
372
+ env: { ...process.env, MEMORAX_CODE_HOME: memoraxCodeHome },
373
+ stdio: ["ignore", "pipe", "pipe"],
374
+ timeout: 10_000,
375
+ windowsHide: true,
376
+ });
377
+ return !result.error && !result.signal && result.status === 0;
378
+ }
379
+
380
+ async function spawnSetupProcess(memoraxCodeHome, { updateMode = false, setupMode = "automatic" } = {}) {
381
+ const env = {
382
+ ...process.env,
383
+ MEMORAX_CODE_HOME: memoraxCodeHome,
384
+ };
385
+ delete env.MEMORAX_CODE_SETUP_UPDATE;
386
+ delete env.MEMORAX_CODE_SETUP_MODE;
387
+ if (updateMode) env.MEMORAX_CODE_SETUP_UPDATE = "1";
388
+ if (setupMode !== "automatic") env.MEMORAX_CODE_SETUP_MODE = setupMode;
389
+ const child = spawn(process.execPath, [join(packageRoot(), "bin", "memorax-code-setup.mjs")], {
390
+ stdio: "inherit",
391
+ env,
392
+ });
393
+ return await new Promise((resolve) => {
394
+ child.on("error", (error) => {
395
+ console.error(`memorax-code setup: failed to start setup: ${error.message}`);
396
+ resolve(1);
397
+ });
398
+ child.on("close", (code, signal) => {
399
+ if (signal) {
400
+ console.error(`memorax-code setup: setup exited from signal ${signal}`);
401
+ resolve(1);
402
+ } else {
403
+ resolve(code ?? 1);
404
+ }
405
+ });
406
+ });
141
407
  }
142
408
 
143
409
  if (process.argv[2] === "update") {
@@ -150,6 +416,24 @@ if (process.argv[2] === "--version" || process.argv[2] === "-v") {
150
416
  process.exit(0);
151
417
  }
152
418
 
419
+ if (process.argv.length === 3 && (process.argv[2] === "--help" || process.argv[2] === "-h")) {
420
+ printMainHelp();
421
+ process.exit(0);
422
+ }
423
+
424
+ if (process.argv[2] === "setup") {
425
+ process.exit(await runSetupCommand(process.argv.slice(3)));
426
+ }
427
+
428
+ if (process.argv[2] === "account") {
429
+ process.exit(await runAccountCommand(process.argv.slice(3)));
430
+ }
431
+
432
+ if (process.argv.length === 2) {
433
+ const exitCode = await routeDefaultCommand();
434
+ if (exitCode !== undefined) process.exit(exitCode);
435
+ }
436
+
153
437
  if (shouldStageClientHookRuntime(process.argv.slice(2))
154
438
  && !truthyEnv(process.env.MEMORAX_CODE_DEFER_CLIENT_HOOK_RUNTIME_ACTIVATION)) {
155
439
  try {
@@ -19,7 +19,8 @@ explicit command/context value > environment variable > config.toml > code fallb
19
19
  ```
20
20
 
21
21
  Use `config.toml` for durable choices and environment variables for temporary
22
- overrides or credentials that should not be written to disk. After editing the
22
+ overrides. Both account-free and existing-account setup write the effective API
23
+ key to this private file so the connection can be reused. After editing the
23
24
  file, run:
24
25
 
25
26
  ```sh
@@ -42,7 +43,7 @@ The generated template selects all four client integrations, disables automatic
42
43
  retrieval, enables automatic writeback, sets the preferred language to Chinese
43
44
  (`zh`), uses a five-turn skill reminder and the adaptive repository-update
44
45
  policy, and enables content-bearing local traces for Codex, Claude Code, and
45
- OpenCode. npm installation may narrow `[clients]` to clients detected on the
46
+ OpenCode. Foreground setup may narrow `[clients]` to clients detected on the
46
47
  host. The tables below list all fallbacks, including tuning fields omitted from
47
48
  the generated file.
48
49
 
@@ -64,25 +65,65 @@ comma-separated subset:
64
65
  --clients codex|claude|dsh|opencode|<comma-separated subset>|all|none
65
66
  ```
66
67
 
67
- A normal npm install or reinstall refreshes `[clients]` from the available
68
- clients detected at that time. OpenCode is available when its explicit, XDG,
69
- or default configuration directory exists, or when `opencode` is on `PATH`.
68
+ Foreground `memorax-code setup` refreshes `[clients]` from the clients
69
+ available at that time. OpenCode is available when its explicit, XDG, or
70
+ default configuration directory exists, or when `opencode` is on `PATH`.
70
71
  DSH is available when at least one valid Profile exists under
71
72
  `$DSH_HOME/profiles`; `DSH_HOME` defaults to `~/.dsh`. An explicit
72
73
  `[clients].dsh = false` is preserved.
73
- Update-mode postinstall runs preserve enabled
74
- clients and also probe each disabled client. An interactive update offers each
75
- runnable disabled integration for activation with a default of yes. Declining
76
- the prompt, or running non-interactively, keeps that integration disabled. A
77
- selected client that is temporarily unavailable also remains selected in the
78
- configuration instead of being permanently disabled. When an update newly
79
- enables Codex, it requests initial Hook activation after the client-selection
80
- prompt.
74
+
75
+ On later setup runs, enabled client intent is preserved. Each newly available
76
+ disabled client is offered for activation with a default of yes; declining
77
+ keeps it disabled. A selected client that is temporarily unavailable remains
78
+ selected instead of being permanently disabled. Direct npm installation does
79
+ not detect clients or modify `[clients]`.
81
80
 
82
81
  Client selection controls managed client-integration lifecycle only. It does
83
82
  not change Codex, Claude Code, DSH, or OpenCode provider settings.
84
83
  `--clients none` runs the Backend without managing a client integration.
85
84
 
85
+ ## Setup and package-transition state
86
+
87
+ npm installation and foreground setup are separate operations.
88
+ `npm install -g @memorax/memorax-code` installs or replaces package files
89
+ without reading terminal input. `memorax-code setup` owns client detection,
90
+ connection setup, configuration writes, Codex Hook activation or review, and
91
+ final readiness checks.
92
+
93
+ Default setup reuses a complete effective connection. Otherwise it detects the
94
+ logged-in operating-system username and maps the system language to `zh` or
95
+ `en`, asking only when a value cannot be detected safely. It then creates or
96
+ restores an account-free credential and writes its API key to `config.toml`.
97
+ `memorax-code setup --existing-account` bypasses automatic reuse and accepts
98
+ an existing connection's username and API key. `--reconfigure` bypasses reuse
99
+ and follows the account-free path again.
100
+
101
+ Successful setup writes a private versioned record at:
102
+
103
+ ```text
104
+ $MEMORAX_CODE_HOME/runtime/setup/setup-completion.json
105
+ ```
106
+
107
+ The record controls only no-argument CLI routing. When it is valid, the command
108
+ shows status. When it is absent and an interactive terminal is available,
109
+ `memorax-code` validates and reuses a complete effective configuration, then
110
+ runs setup and reconciliation once to write the record. If the configuration
111
+ is incomplete or no interactive terminal is available, it points to
112
+ `memorax-code setup`. Invalid and unsupported records fail closed. A complete
113
+ product uninstall removes this marker while retaining `config.toml`; stop and
114
+ partial client uninstall preserve it.
115
+
116
+ Replacing a running managed Backend uses a separate private record:
117
+
118
+ ```text
119
+ $MEMORAX_CODE_HOME/runtime/install/package-transition.json
120
+ ```
121
+
122
+ Preinstall records and retires the running installation. Postinstall restores
123
+ and verifies it before consuming the record. A fresh or already-stopped
124
+ installation has no transition and remains stopped. Do not edit either runtime
125
+ record by hand.
126
+
86
127
  ## DeepSeek Harness integration paths
87
128
 
88
129
  DSH Profiles are discovered under:
@@ -145,7 +186,7 @@ MemoraX is the required remote-memory service:
145
186
  ```toml
146
187
  [memorax]
147
188
  endpoint = "https://platform.memorax.net"
148
- user_id = "your-base-user-id"
189
+ user_id = "your-username"
149
190
  api_key = "your-api-key"
150
191
  # timeout_ms = 5000
151
192
  # startup_timeout_ms = 3000
@@ -154,8 +195,8 @@ api_key = "your-api-key"
154
195
  | Field | Environment override | Fallback |
155
196
  | --- | --- | --- |
156
197
  | `endpoint` | `MEMORAX_CODE_MEMORAX_ENDPOINT` | `https://platform.memorax.net` |
157
- | `user_id` | `MEMORAX_CODE_MEMORAX_USER_ID` | required |
158
- | `api_key` | `MEMORAX_CODE_MEMORAX_API_KEY` | required |
198
+ | `user_id` | `MEMORAX_CODE_MEMORAX_USER_ID` | required username |
199
+ | `api_key` | `MEMORAX_CODE_MEMORAX_API_KEY` | required; setup writes it |
159
200
  | `timeout_ms` | `MEMORAX_CODE_MEMORAX_TIMEOUT_MS` | `5000` ms |
160
201
  | `startup_timeout_ms` | `MEMORAX_CODE_MEMORAX_STARTUP_TIMEOUT_MS` | `3000` ms |
161
202
 
@@ -163,8 +204,14 @@ MemoraX requests send the API key and the query or content required by the
163
204
  selected memory operation to the HTTPS endpoint. Override `endpoint` only with
164
205
  a compatible MemoraX service you trust.
165
206
 
207
+ Quota reminders keep only a one-way connection fingerprint and the last
208
+ notified level for memory write and memory search under the private runtime
209
+ directory. They do not store a raw API key, Mark ID, or account-registration
210
+ state. The returned quota limit is used only to decide whether to include
211
+ conditional anonymous-account guidance.
212
+
166
213
  `startup_timeout_ms` controls synchronous automatic retrieval and is capped at
167
- 10 seconds. `user_id` is a base identity; MemoraX Code derives a
214
+ 10 seconds. `user_id` is the configured username; MemoraX Code derives a
168
215
  repository-scoped identity for Git workspaces and a folder-scoped identity for
169
216
  non-Git workspaces. It never falls back to the unscoped base identity.
170
217
 
@@ -341,6 +388,8 @@ token. Persistent connection, token, and PID records live under
341
388
  read or parsed; memory readers may also warn. Unsupported field types are
342
389
  ignored.
343
390
  - Targeted configuration updates preserve unrelated and unknown TOML content.
391
+ - Setup writes completion only after Backend, client, and effective MemoraX
392
+ readiness checks succeed.
344
393
  - Invalid or unsupported Backend runtime records fail closed instead of
345
394
  silently falling back to `127.0.0.1:8787`.
346
395
 
@@ -18,17 +18,83 @@ memory switches without printing secrets. Codex, Claude Code, and OpenCode
18
18
  also provide client-specific `doctor` commands; DSH uses the shared lifecycle
19
19
  status.
20
20
 
21
+ ## Package installed, but setup did not start
22
+
23
+ This is expected after:
24
+
25
+ ```sh
26
+ npm install -g @memorax/memorax-code
27
+ ```
28
+
29
+ npm installation is deliberately non-interactive. Start setup from a normal
30
+ terminal:
31
+
32
+ ```sh
33
+ memorax-code setup
34
+ ```
35
+
36
+ If a complete configuration was retained from an earlier installation,
37
+ default setup reuses it automatically. Use `memorax-code setup --reconfigure`
38
+ to replace it, or `memorax-code setup --existing-account` to enter an
39
+ existing MemoraX connection.
40
+
41
+ Setup requires terminal input and terminal-visible stderr. A pipe, background
42
+ process, or redirected stdin/stderr cannot complete setup; rerun it in a normal
43
+ interactive terminal.
44
+
45
+ ## Setup does not complete
46
+
47
+ Setup writes
48
+ `$MEMORAX_CODE_HOME/runtime/setup/setup-completion.json` only after
49
+ configuration, client and Hook reconciliation, Backend start, and final
50
+ readiness checks succeed. Until then, running `memorax-code` with no command
51
+ points back to `memorax-code setup`.
52
+
53
+ If secure credential setup fails, confirm that the operating-system credential
54
+ backend is available to the same logged-in user and that the MemoraX service is
55
+ reachable. On Linux, confirm that `/usr/bin/secret-tool` is installed and the
56
+ session can reach an unlocked Secret Service. Minimal containers and detached
57
+ SSH sessions often do not provide one.
58
+
59
+ Malformed `config.toml` is preserved rather than overwritten. Repair or
60
+ restore the file, then rerun setup. Invalid setup-completion records also fail
61
+ closed; preserve a diagnostic copy and confirm no setup command is active
62
+ before moving an invalid record aside. An unsupported record version requires
63
+ a compatible MemoraX Code release.
64
+
65
+ ## npm package transition fails
66
+
67
+ Replacing a running managed installation uses
68
+ `$MEMORAX_CODE_HOME/runtime/install/package-transition.json`. If preinstall
69
+ cannot retire the old Backend, installation stops before package replacement.
70
+ If postinstall cannot start or verify the new Backend, the retired transition
71
+ is retained for a bounded retry.
72
+
73
+ Do not delete the record while the old Backend or another lifecycle command may
74
+ still own state. After confirming process ownership, retry:
75
+
76
+ ```sh
77
+ memorax-code stop --clients none
78
+ npm install -g @memorax/memorax-code
79
+ ```
80
+
81
+ Fresh and already-stopped installations do not create a transition and remain
82
+ stopped.
83
+
21
84
  ## Installed, but memory is unavailable
22
85
 
23
86
  The package and Backend can be healthy while MemoraX remains unconfigured. Run:
24
87
 
25
88
  ```sh
89
+ memorax-code setup
26
90
  memorax-cli status
27
91
  ```
28
92
 
29
- Configure `endpoint`, `user_id`, and `api_key` under `[memorax]` in
30
- `$MEMORAX_CODE_HOME/config.toml`, or set their environment equivalents. The
31
- current default endpoint is `https://platform.memorax.net`.
93
+ Default setup creates or restores an account-free connection. For an existing
94
+ account, run `memorax-code setup --existing-account`. A manually managed
95
+ connection may instead configure `endpoint`, `user_id`, and `api_key`
96
+ under `[memorax]`, or set their environment equivalents. The current default
97
+ endpoint is `https://platform.memorax.net`.
32
98
 
33
99
  After changing persistent configuration:
34
100
 
@@ -42,6 +108,29 @@ search. Automatic writeback requires `[memory.writeback] enabled = true` and
42
108
  must not be disabled by
43
109
  `MEMORAX_CODE_MEMORAX_WRITEBACK_ENABLED=false`.
44
110
 
111
+ ## Quota reminder and Mark ID
112
+
113
+ Memory write and memory search reminders are tracked independently. A reminder
114
+ is emitted when the corresponding remaining quota reaches 10% or less and
115
+ again at 0%; raw quota counts are not shown.
116
+
117
+ Automatic quota reminders are currently supported in Codex, Claude Code, and
118
+ OpenCode. DeepSeek Harness does not currently surface these reminders.
119
+
120
+ Routine reminders do not include a complete Mark ID. If this device uses an
121
+ unregistered anonymous identity and the MemoraX account page requires its Mark
122
+ ID, run this command yourself in a local terminal:
123
+
124
+ ```sh
125
+ memorax-code account --show-mark-id
126
+ ```
127
+
128
+ The command reads a ready local trial identity and prints only its Mark ID. Do
129
+ not ask an Agent to run it or paste the output into a conversation, screenshot,
130
+ or log. If no ready local trial identity exists, use `memorax-code setup`; a
131
+ connection copied from another computer does not include that computer's
132
+ device-local Mark ID.
133
+
45
134
  ## Backend does not start
46
135
 
47
136
  ```sh
@@ -91,9 +180,10 @@ memorax-code start --clients codex
91
180
  memorax-code-codex doctor
92
181
  ```
93
182
 
94
- Codex requires review for new or changed Hook command hashes. A declined or
95
- non-interactive update can leave Hooks untrusted even though the update
96
- succeeded. Do not write trust entries directly. If the skill is missing, rerun
183
+ Codex requires review for new or changed Hook command hashes. A declined,
184
+ non-interactive, or direct npm update can leave changed Hooks untrusted even
185
+ though package replacement succeeded. Run `memorax-code setup` for foreground
186
+ review; do not write trust entries directly. If the skill is missing, rerun
97
187
  `memorax-code start --clients codex`, then restart or refresh Codex.
98
188
 
99
189
  ## Claude Code plugin or Hook is inactive
@@ -116,10 +206,18 @@ memorax-code start --clients dsh
116
206
  memorax-code status --clients dsh
117
207
  ```
118
208
 
209
+ Automatic DSH discovery is optional: an unavailable DSH integration is
210
+ reported as degraded without blocking the Backend or another detected client.
211
+ The explicit commands above are strict and return a failure until DSH is ready.
212
+
119
213
  MemoraX Code discovers existing Profiles under `$DSH_HOME/profiles`;
120
214
  `DSH_HOME` defaults to `~/.dsh`. A `no_existing_profiles` result means DSH has
121
215
  not created a valid Profile in that home. A `dsh_version_unavailable` result
122
- means the selected `dsh` command did not return a valid semantic version. The
216
+ means neither the selected DSH command nor an existing Profile-linked DSH
217
+ runtime supplied a valid semantic version. A `dsh_profile_runtime_stale` result
218
+ means that Profile-linked package is invalid or its original package cache is
219
+ no longer available. Repair or relaunch DSH itself, then rerun the MemoraX Code
220
+ start command. MemoraX Code never invokes `npx` or installs or updates DSH. The
123
221
  tested baseline is `0.1.0-rc.6`; another valid version is allowed but marked
124
222
  untested. A `pnpm_not_found` result means DSH's native Profile plugin manager
125
223
  could not find `pnpm` on `PATH`; install `pnpm`, then rerun the start command.
@@ -4,6 +4,10 @@ export type JsonFileLockOptions = Readonly<{
4
4
  retryMs?: number;
5
5
  }>;
6
6
 
7
+ export type AsyncJsonFileLockOptions = JsonFileLockOptions & Readonly<{
8
+ signal?: AbortSignal;
9
+ }>;
10
+
7
11
  export function readAdapterState(path: string): any;
8
12
  export function readJsonFile(path: string): any;
9
13
  export function readJsonValue(path: string): any;
@@ -23,5 +27,5 @@ export function withJsonFileLock<T>(
23
27
  export function withJsonFileLockAsync<T>(
24
28
  path: string,
25
29
  operation: () => T | Promise<T>,
26
- options?: JsonFileLockOptions,
30
+ options?: AsyncJsonFileLockOptions,
27
31
  ): Promise<T>;