recallx 1.1.0 → 1.2.0

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 CHANGED
@@ -43,7 +43,7 @@ Use the public repo when you want the full source-run surface:
43
43
 
44
44
  - local API under `/api/v1`
45
45
  - source-run renderer workflow through `npm run dev`
46
- - stdio MCP bridge through `npm run mcp`
46
+ - stdio MCP bridge through `npm run dev:mcp` during source development
47
47
  - runtime workspace create/open switching without restarting the service
48
48
 
49
49
  ```bash
@@ -56,6 +56,13 @@ npm run dev
56
56
  MCP from source:
57
57
 
58
58
  ```bash
59
+ npm run dev:mcp
60
+ ```
61
+
62
+ If you want to run the built MCP entrypoint instead, build the server first:
63
+
64
+ ```bash
65
+ npm run build:server
59
66
  npm run mcp
60
67
  ```
61
68
 
@@ -88,6 +95,18 @@ When you are preparing a release, bump from the highest known version instead of
88
95
  npm run version:bump -- patch
89
96
  ```
90
97
 
98
+ Workspace lifecycle and backup commands from the same source checkout:
99
+
100
+ ```bash
101
+ recallx workspace current
102
+ recallx workspace backups
103
+ recallx workspace backup --label "before-upgrade"
104
+ recallx workspace export --format markdown
105
+ recallx workspace restore --backup <id> --root /path/to/restore
106
+ ```
107
+
108
+ The renderer Workspace page exposes the same backup, export, restore, and single-writer safety warnings over the local API.
109
+
91
110
  If you want an installable runtime instead of source-run workflows, use one of the npm distribution paths below.
92
111
 
93
112
  ## 2. npm Full Runtime (`recallx`)
@@ -118,6 +137,15 @@ The full npm package includes:
118
137
 
119
138
  `recallx mcp install` writes a stable launcher to `~/.recallx/bin/recallx-mcp`, which is the recommended command path for Codex and other editor MCP configs.
120
139
 
140
+ Workspace backup and recovery commands are available in the packaged CLI too:
141
+
142
+ ```bash
143
+ recallx workspace backups
144
+ recallx workspace backup --label "before-upgrade"
145
+ recallx workspace export --format json
146
+ recallx workspace restore --backup <id> --root /path/to/restore
147
+ ```
148
+
121
149
  If the API is running in bearer mode, set `RECALLX_API_TOKEN` in the MCP client environment. The launcher does not write tokens to disk.
122
150
 
123
151
  Start the packaged runtime with:
@@ -228,11 +256,14 @@ RecallX also ships a stdio MCP adapter for agent clients that prefer tool discov
228
256
  MCP tool results keep `structuredContent` as the authoritative machine-readable payload, while `content.text` is rendered as a compact deterministic summary instead of a pretty-printed JSON mirror when the payload shape is known.
229
257
 
230
258
  ```bash
259
+ npm run dev:mcp
231
260
  npm run mcp
232
261
  node dist/server/app/mcp/index.js --api http://127.0.0.1:8787/api/v1
233
262
  recallx-mcp --api http://127.0.0.1:8787/api/v1
234
263
  ```
235
264
 
265
+ Use `npm run dev:mcp` during source development. `npm run mcp` runs the built entrypoint, so it expects `npm run build:server` to have already created `dist/server/app/mcp/index.js`.
266
+
236
267
  For launcher paths, environment variables, and editor-specific setup, see `docs/mcp.md`.
237
268
 
238
269
  ## Docs
@@ -243,6 +274,7 @@ For launcher paths, environment variables, and editor-specific setup, see `docs/
243
274
  - `docs/api.md` for the local HTTP and CLI contract
244
275
  - `docs/mcp.md` for MCP bridge setup
245
276
  - `docs/workflows.md` for common usage flows
277
+ - `docs/sync-backup.md` for backup, restore, and single-writer multi-device guidance
246
278
  - `docs/schema.md` for storage and data model details
247
279
 
248
280
  ## License
@@ -6,7 +6,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
6
6
  import { getApiBase, getAuthToken, requestJson } from "./http.js";
7
7
  import { RECALLX_VERSION } from "../../shared/version.js";
8
8
  import { applyCliUpdate, getCliUpdatePlan } from "./update.js";
9
- import { renderActivitySearchResults, renderBundleMarkdown, renderGovernanceIssues, renderJson, renderNode, renderRelated, renderSearchResults, renderTelemetryErrors, renderTelemetrySummary, renderText, renderUpdateResult, renderWorkspaceSearchResults, renderWorkspaces, } from "./format.js";
9
+ import { renderActivitySearchResults, renderBundleMarkdown, renderGovernanceIssues, renderJson, renderNode, renderRelated, renderSearchResults, renderTelemetryErrors, renderTelemetrySummary, renderText, renderUpdateResult, renderWorkspaceBackups, renderWorkspaceSearchResults, renderWorkspaces, } from "./format.js";
10
10
  const DEFAULT_SOURCE = {
11
11
  actorType: "human",
12
12
  actorLabel: "recallx-cli",
@@ -465,6 +465,27 @@ async function runWorkspace(apiBase, token, format, args, positionals) {
465
465
  action,
466
466
  rootPath: args.root || args.path || positionals[1],
467
467
  });
468
+ case "backups": {
469
+ const data = await requestJson(apiBase, "/workspaces/backups", { token });
470
+ outputData(data, format, "workspace-backups");
471
+ return;
472
+ }
473
+ case "backup":
474
+ return runPostCommand(apiBase, token, format, "/workspaces/backups", "workspace-backup", {
475
+ label: args.label || args.name || positionals[1],
476
+ });
477
+ case "export":
478
+ return runPostCommand(apiBase, token, format, "/workspaces/export", "workspace-export", {
479
+ format: args.format || args.kind || "json",
480
+ });
481
+ case "restore":
482
+ validateRequired(args.backup || args.id || positionals[1], "workspace restore requires --backup");
483
+ validateRequired(args.root || args.path || positionals[2], "workspace restore requires --root");
484
+ return runPostCommand(apiBase, token, format, "/workspaces/restore", "workspace-restore", {
485
+ backupId: args.backup || args.id || positionals[1],
486
+ targetRootPath: args.root || args.path || positionals[2],
487
+ workspaceName: args.name || args.title,
488
+ });
468
489
  }
469
490
  throw new Error(`Unknown workspace action: ${action}`);
470
491
  }
@@ -547,6 +568,9 @@ function outputData(data, format, command) {
547
568
  case "workspace-list":
548
569
  writeStdout(renderWorkspaces(payload));
549
570
  return;
571
+ case "workspace-backups":
572
+ writeStdout(renderWorkspaceBackups(payload));
573
+ return;
550
574
  case "append":
551
575
  case "create":
552
576
  case "link":
@@ -557,6 +581,9 @@ function outputData(data, format, command) {
557
581
  case "workspace-current":
558
582
  case "workspace-create":
559
583
  case "workspace-open":
584
+ case "workspace-backup":
585
+ case "workspace-export":
586
+ case "workspace-restore":
560
587
  writeStdout(renderText(payload));
561
588
  return;
562
589
  case "observability-summary":
@@ -696,6 +723,10 @@ Usage:
696
723
  recallx workspace list
697
724
  recallx workspace create --root /path/to/workspace [--name "Personal"]
698
725
  recallx workspace open --root /path/to/workspace
726
+ recallx workspace backups
727
+ recallx workspace backup [--label "before-upgrade"]
728
+ recallx workspace export [--format json|markdown]
729
+ recallx workspace restore --backup <id> --root /path/to/restore [--name "Recovered"]
699
730
  recallx observability summary [--since 24h]
700
731
  recallx observability errors [--since 24h] [--surface mcp] [--limit 50]
701
732
 
@@ -144,6 +144,20 @@ export function renderWorkspaces(data) {
144
144
  .join("\n\n")}\n`;
145
145
  }
146
146
 
147
+ export function renderWorkspaceBackups(data) {
148
+ const items = data?.items || [];
149
+ if (!items.length) {
150
+ return "No backups.\n";
151
+ }
152
+
153
+ return `${items
154
+ .map(
155
+ (item, index) =>
156
+ `${index + 1}. ${item.label || item.id}\n id: ${item.id}\n created: ${item.createdAt}\n path: ${item.backupPath}`,
157
+ )
158
+ .join("\n\n")}\n`;
159
+ }
160
+
147
161
  export function renderUpdateResult(data) {
148
162
  const lines = [
149
163
  `package: ${data?.packageName || ""}`,