clawon 0.1.10 → 0.1.11

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 +10 -2
  2. package/dist/index.js +38 -19
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -22,6 +22,7 @@ Local backups are stored in `~/.clawon/backups/` as standard `.tar.gz` archives.
22
22
  npx clawon local backup
23
23
  npx clawon local backup --tag "before migration"
24
24
  npx clawon local backup --include-memory-db # Include SQLite memory index
25
+ npx clawon local backup --include-sessions # Include chat history
25
26
  npx clawon local backup --max-snapshots 10 # Keep only 10 most recent
26
27
 
27
28
  # List all local backups
@@ -42,6 +43,7 @@ Set up automatic backups via cron (macOS/Linux only).
42
43
  npx clawon local schedule on
43
44
  npx clawon local schedule on --every 6h --max-snapshots 10
44
45
  npx clawon local schedule on --include-memory-db
46
+ npx clawon local schedule on --include-sessions
45
47
 
46
48
  # Disable local schedule
47
49
  npx clawon local schedule off
@@ -59,7 +61,11 @@ npx clawon schedule status
59
61
  Cloud backups sync your workspace to Clawon's servers for cross-machine access.
60
62
 
61
63
  ```bash
62
- # Authenticate
64
+ # Authenticate (env var recommended to avoid shell history)
65
+ export CLAWON_API_KEY=<your-key>
66
+ npx clawon login
67
+
68
+ # Or inline (key may appear in shell history)
63
69
  npx clawon login --api-key <your-key>
64
70
 
65
71
  # Create a cloud backup
@@ -67,6 +73,7 @@ npx clawon backup
67
73
  npx clawon backup --tag "stable config"
68
74
  npx clawon backup --dry-run # Preview without uploading
69
75
  npx clawon backup --include-memory-db # Requires Pro account
76
+ npx clawon backup --include-sessions # Requires Hobby or Pro
70
77
 
71
78
  # List cloud backups
72
79
  npx clawon list
@@ -88,6 +95,7 @@ npx clawon activity # Recent events
88
95
  ```bash
89
96
  npx clawon discover # Show exactly which files would be backed up
90
97
  npx clawon discover --include-memory-db # Include SQLite memory index
98
+ npx clawon discover --include-sessions # Include chat history
91
99
  npx clawon schedule status # Show active schedules
92
100
  npx clawon status # Connection status and file count
93
101
  npx clawon logout # Remove local credentials
@@ -122,7 +130,7 @@ These are **always excluded**, even if they match an include pattern:
122
130
  | `openclaw.json` | May contain credentials |
123
131
  | `agents/*/auth.json` | Authentication data |
124
132
  | `agents/*/auth-profiles.json` | Auth profiles |
125
- | `agents/*/sessions/**` | Chat history (large, use future `--include-sessions`) |
133
+ | `agents/*/sessions/**` | Chat history (large, use `--include-sessions` to include) |
126
134
  | `memory/lancedb/**` | Vector database (binary, large) |
127
135
  | `memory/*.sqlite` | SQLite databases (use `--include-memory-db` to include) |
128
136
  | `*.lock`, `*.wal`, `*.shm` | Database lock files |
package/dist/index.js CHANGED
@@ -76,10 +76,13 @@ function matchGlob(filePath, pattern) {
76
76
  let regexPattern = pattern.replace(/\./g, "\\.").replace(/\*\*\//g, "(.*/)?").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*");
77
77
  return new RegExp(`^${regexPattern}$`).test(filePath);
78
78
  }
79
- function shouldInclude(relativePath, includeMemoryDb = false) {
79
+ function shouldInclude(relativePath, includeMemoryDb = false, includeSessions = false) {
80
80
  if (includeMemoryDb && matchGlob(relativePath, "memory/*.sqlite")) {
81
81
  return true;
82
82
  }
83
+ if (includeSessions && matchGlob(relativePath, "agents/*/sessions/**")) {
84
+ return true;
85
+ }
83
86
  for (const pattern of EXCLUDE_PATTERNS) {
84
87
  if (matchGlob(relativePath, pattern)) return false;
85
88
  }
@@ -88,7 +91,7 @@ function shouldInclude(relativePath, includeMemoryDb = false) {
88
91
  }
89
92
  return false;
90
93
  }
91
- function discoverFiles(baseDir, includeMemoryDb = false) {
94
+ function discoverFiles(baseDir, includeMemoryDb = false, includeSessions = false) {
92
95
  const files = [];
93
96
  function walk(dir, relativePath = "") {
94
97
  if (!fs.existsSync(dir)) return;
@@ -99,7 +102,7 @@ function discoverFiles(baseDir, includeMemoryDb = false) {
99
102
  if (entry.isDirectory()) {
100
103
  walk(fullPath, relPath);
101
104
  } else if (entry.isFile()) {
102
- if (shouldInclude(relPath, includeMemoryDb)) {
105
+ if (shouldInclude(relPath, includeMemoryDb, includeSessions)) {
103
106
  const stats = fs.statSync(fullPath);
104
107
  files.push({
105
108
  path: relPath,
@@ -112,13 +115,14 @@ function discoverFiles(baseDir, includeMemoryDb = false) {
112
115
  walk(baseDir);
113
116
  return files;
114
117
  }
115
- async function createLocalArchive(files, openclawDir, outputPath, tag, includeMemoryDb, trigger) {
118
+ async function createLocalArchive(files, openclawDir, outputPath, tag, includeMemoryDb, includeSessions, trigger) {
116
119
  const meta = {
117
120
  version: 2,
118
121
  created: (/* @__PURE__ */ new Date()).toISOString(),
119
122
  ...tag ? { tag } : {},
120
123
  file_count: files.length,
121
124
  ...includeMemoryDb ? { include_memory_db: true } : {},
125
+ ...includeSessions ? { include_sessions: true } : {},
122
126
  ...trigger ? { trigger } : {}
123
127
  };
124
128
  const metaPath = path.join(openclawDir, "_clawon_meta.json");
@@ -236,15 +240,20 @@ function assertNotWindows() {
236
240
  }
237
241
  var program = new Command();
238
242
  program.name("clawon").description("Backup and restore your OpenClaw workspace").version("0.1.1");
239
- program.command("login").description("Connect to Clawon with your API key").requiredOption("--api-key <key>", "Your Clawon API key").option("--api-url <url>", "API base URL", "https://clawon.io").action(async (opts) => {
243
+ program.command("login").description("Connect to Clawon with your API key").option("--api-key <key>", "Your Clawon API key (or set CLAWON_API_KEY env var)").option("--api-url <url>", "API base URL", "https://clawon.io").action(async (opts) => {
244
+ const apiKey = opts.apiKey || process.env.CLAWON_API_KEY;
245
+ if (!apiKey) {
246
+ console.error("\u2717 API key required. Use --api-key <key> or set CLAWON_API_KEY environment variable.");
247
+ process.exit(1);
248
+ }
240
249
  try {
241
- const connectJson = await api(opts.apiUrl, "/api/v1/profile/connect", "POST", opts.apiKey, {
250
+ const connectJson = await api(opts.apiUrl, "/api/v1/profile/connect", "POST", apiKey, {
242
251
  profileName: "default",
243
252
  instanceName: os.hostname(),
244
253
  syncIntervalMinutes: 60
245
254
  });
246
255
  writeConfig({
247
- apiKey: opts.apiKey,
256
+ apiKey,
248
257
  profileId: connectJson.profileId,
249
258
  apiBaseUrl: opts.apiUrl,
250
259
  connectedAt: (/* @__PURE__ */ new Date()).toISOString()
@@ -257,11 +266,15 @@ program.command("login").description("Connect to Clawon with your API key").requ
257
266
  process.exit(1);
258
267
  }
259
268
  });
260
- program.command("backup").description("Backup your OpenClaw workspace to the cloud").option("--dry-run", "Show what would be backed up without uploading").option("--tag <label>", "Add a label to this backup").option("--include-memory-db", "Include SQLite memory index").option("--scheduled", "Internal: triggered by cron (suppresses interactive output)").action(async (opts) => {
269
+ program.command("backup").description("Backup your OpenClaw workspace to the cloud").option("--dry-run", "Show what would be backed up without uploading").option("--tag <label>", "Add a label to this backup").option("--include-memory-db", "Include SQLite memory index").option("--include-sessions", "Include chat history (sessions)").option("--scheduled", "Internal: triggered by cron (suppresses interactive output)").action(async (opts) => {
261
270
  if (opts.includeMemoryDb) {
262
271
  console.error("\u2717 Memory DB cloud backup requires a Pro account. Use `clawon local backup --include-memory-db` for local backups.");
263
272
  process.exit(1);
264
273
  }
274
+ if (opts.includeSessions) {
275
+ console.error("\u2717 Session backup requires a Hobby or Pro account. Use `clawon local backup --include-sessions` for local backups.");
276
+ process.exit(1);
277
+ }
265
278
  const cfg = readConfig();
266
279
  if (!cfg) {
267
280
  console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
@@ -335,6 +348,7 @@ program.command("backup").description("Backup your OpenClaw workspace to the clo
335
348
  file_count: files.length,
336
349
  total_bytes: totalSize,
337
350
  include_memory_db: !!opts.includeMemoryDb,
351
+ include_sessions: !!opts.includeSessions,
338
352
  type: "cloud",
339
353
  trigger: opts.scheduled ? "scheduled" : "manual"
340
354
  });
@@ -546,12 +560,12 @@ program.command("delete [id]").description("Delete a snapshot").option("--oldest
546
560
  process.exit(1);
547
561
  }
548
562
  });
549
- program.command("discover").description("Preview which files would be included in a backup").option("--include-memory-db", "Include SQLite memory index").action(async (opts) => {
563
+ program.command("discover").description("Preview which files would be included in a backup").option("--include-memory-db", "Include SQLite memory index").option("--include-sessions", "Include chat history (sessions)").action(async (opts) => {
550
564
  if (!fs.existsSync(OPENCLAW_DIR)) {
551
565
  console.error(`\u2717 OpenClaw directory not found: ${OPENCLAW_DIR}`);
552
566
  process.exit(1);
553
567
  }
554
- const files = discoverFiles(OPENCLAW_DIR, !!opts.includeMemoryDb);
568
+ const files = discoverFiles(OPENCLAW_DIR, !!opts.includeMemoryDb, !!opts.includeSessions);
555
569
  if (files.length === 0) {
556
570
  console.log("No files matched the include patterns.");
557
571
  return;
@@ -576,7 +590,7 @@ program.command("discover").description("Preview which files would be included i
576
590
  Total: ${files.length} files (${(totalSize / 1024).toFixed(1)} KB)`);
577
591
  console.log(`Source: ${OPENCLAW_DIR}`);
578
592
  const cfg = readConfig();
579
- trackCliEvent(cfg?.profileId || "anonymous", "cli_discover", { file_count: files.length, include_memory_db: !!opts.includeMemoryDb });
593
+ trackCliEvent(cfg?.profileId || "anonymous", "cli_discover", { file_count: files.length, include_memory_db: !!opts.includeMemoryDb, include_sessions: !!opts.includeSessions });
580
594
  });
581
595
  var schedule = program.command("schedule").description("Manage scheduled cloud backups");
582
596
  schedule.command("on").description("Enable scheduled cloud backups via cron").option("--every <interval>", "Backup interval: 1h, 6h, 12h, 24h", "12h").action(async (opts) => {
@@ -617,6 +631,7 @@ schedule.command("status").description("Show schedule status").action(async () =
617
631
  if (localCfg?.intervalHours) console.log(` Interval: every ${localCfg.intervalHours}h`);
618
632
  if (localCfg?.maxSnapshots) console.log(` Max snapshots: ${localCfg.maxSnapshots}`);
619
633
  if (localCfg?.includeMemoryDb) console.log(` Memory DB: included`);
634
+ if (localCfg?.includeSessions) console.log(` Sessions: included`);
620
635
  console.log(` Cron: ${localEntry.trim()}`);
621
636
  } else {
622
637
  console.log("\u2717 Local schedule: inactive");
@@ -684,7 +699,7 @@ Total: ${files.length} files`);
684
699
  });
685
700
  var local = program.command("local").description("Local backup and restore (no cloud required)");
686
701
  var localSchedule = local.command("schedule").description("Manage scheduled local backups");
687
- localSchedule.command("on").description("Enable scheduled local backups via cron").option("--every <interval>", "Backup interval: 1h, 6h, 12h, 24h", "12h").option("--max-snapshots <n>", "Keep only the N most recent local backups").option("--include-memory-db", "Include SQLite memory index").action(async (opts) => {
702
+ localSchedule.command("on").description("Enable scheduled local backups via cron").option("--every <interval>", "Backup interval: 1h, 6h, 12h, 24h", "12h").option("--max-snapshots <n>", "Keep only the N most recent local backups").option("--include-memory-db", "Include SQLite memory index").option("--include-sessions", "Include chat history (sessions)").action(async (opts) => {
688
703
  assertNotWindows();
689
704
  const interval = opts.every;
690
705
  if (!VALID_INTERVALS.includes(interval)) {
@@ -694,7 +709,7 @@ localSchedule.command("on").description("Enable scheduled local backups via cron
694
709
  const cfg = readConfig();
695
710
  const wasEnabled = cfg?.schedule?.local?.enabled;
696
711
  const cronExpr = INTERVAL_CRON[interval];
697
- const args = "local backup --scheduled" + (opts.includeMemoryDb ? " --include-memory-db" : "") + (opts.maxSnapshots ? ` --max-snapshots ${opts.maxSnapshots}` : "");
712
+ const args = "local backup --scheduled" + (opts.includeMemoryDb ? " --include-memory-db" : "") + (opts.includeSessions ? " --include-sessions" : "") + (opts.maxSnapshots ? ` --max-snapshots ${opts.maxSnapshots}` : "");
698
713
  const command = resolveCliCommand(args);
699
714
  addCronEntry(CRON_MARKER_LOCAL, cronExpr, command);
700
715
  const maxSnapshots = opts.maxSnapshots ? parseInt(opts.maxSnapshots, 10) : null;
@@ -704,7 +719,8 @@ localSchedule.command("on").description("Enable scheduled local backups via cron
704
719
  enabled: true,
705
720
  intervalHours: parseInt(interval),
706
721
  ...maxSnapshots ? { maxSnapshots } : {},
707
- ...opts.includeMemoryDb ? { includeMemoryDb: true } : {}
722
+ ...opts.includeMemoryDb ? { includeMemoryDb: true } : {},
723
+ ...opts.includeSessions ? { includeSessions: true } : {}
708
724
  }
709
725
  }
710
726
  });
@@ -712,8 +728,9 @@ localSchedule.command("on").description("Enable scheduled local backups via cron
712
728
  console.log(` Interval: every ${interval}`);
713
729
  if (maxSnapshots) console.log(` Max snapshots: ${maxSnapshots}`);
714
730
  if (opts.includeMemoryDb) console.log(` Memory DB: included`);
731
+ if (opts.includeSessions) console.log(` Sessions: included`);
715
732
  console.log(` Log: ${SCHEDULE_LOG}`);
716
- const firstRunArgs = "local backup" + (opts.includeMemoryDb ? " --include-memory-db" : "") + (opts.maxSnapshots ? ` --max-snapshots ${opts.maxSnapshots}` : "");
733
+ const firstRunArgs = "local backup" + (opts.includeMemoryDb ? " --include-memory-db" : "") + (opts.includeSessions ? " --include-sessions" : "") + (opts.maxSnapshots ? ` --max-snapshots ${opts.maxSnapshots}` : "");
717
734
  console.log("\nRunning first backup now...\n");
718
735
  try {
719
736
  execSync(resolveCliCommand(firstRunArgs), { stdio: "inherit" });
@@ -724,7 +741,8 @@ localSchedule.command("on").description("Enable scheduled local backups via cron
724
741
  type: "local",
725
742
  interval_hours: parseInt(interval),
726
743
  max_snapshots: maxSnapshots,
727
- include_memory_db: !!opts.includeMemoryDb
744
+ include_memory_db: !!opts.includeMemoryDb,
745
+ include_sessions: !!opts.includeSessions
728
746
  });
729
747
  });
730
748
  localSchedule.command("off").description("Disable scheduled local backups").action(async () => {
@@ -743,14 +761,14 @@ localSchedule.command("off").description("Disable scheduled local backups").acti
743
761
  const cfg = readConfig();
744
762
  trackCliEvent(cfg?.profileId || "anonymous", "schedule_disabled", { type: "local" });
745
763
  });
746
- local.command("backup").description("Save a local backup of your OpenClaw workspace").option("--tag <label>", "Add a label to this backup").option("--include-memory-db", "Include SQLite memory index").option("--scheduled", "Internal: triggered by cron (suppresses interactive output)").option("--max-snapshots <n>", "Keep only the N most recent local backups").action(async (opts) => {
764
+ local.command("backup").description("Save a local backup of your OpenClaw workspace").option("--tag <label>", "Add a label to this backup").option("--include-memory-db", "Include SQLite memory index").option("--include-sessions", "Include chat history (sessions)").option("--scheduled", "Internal: triggered by cron (suppresses interactive output)").option("--max-snapshots <n>", "Keep only the N most recent local backups").action(async (opts) => {
747
765
  if (!fs.existsSync(OPENCLAW_DIR)) {
748
766
  console.error(`\u2717 OpenClaw directory not found: ${OPENCLAW_DIR}`);
749
767
  process.exit(1);
750
768
  }
751
769
  try {
752
770
  if (!opts.scheduled) console.log("Discovering files...");
753
- const files = discoverFiles(OPENCLAW_DIR, !!opts.includeMemoryDb);
771
+ const files = discoverFiles(OPENCLAW_DIR, !!opts.includeMemoryDb, !!opts.includeSessions);
754
772
  if (files.length === 0) {
755
773
  console.error("\u2717 No files found to backup");
756
774
  process.exit(1);
@@ -762,7 +780,7 @@ local.command("backup").description("Save a local backup of your OpenClaw worksp
762
780
  const filename = `backup-${timestamp}.tar.gz`;
763
781
  const filePath = path.join(BACKUPS_DIR, filename);
764
782
  if (!opts.scheduled) console.log("Creating archive...");
765
- await createLocalArchive(files, OPENCLAW_DIR, filePath, opts.tag, opts.includeMemoryDb, opts.scheduled ? "scheduled" : "manual");
783
+ await createLocalArchive(files, OPENCLAW_DIR, filePath, opts.tag, opts.includeMemoryDb, opts.includeSessions, opts.scheduled ? "scheduled" : "manual");
766
784
  const archiveSize = fs.statSync(filePath).size;
767
785
  if (!opts.scheduled) {
768
786
  console.log(`
@@ -792,6 +810,7 @@ local.command("backup").description("Save a local backup of your OpenClaw worksp
792
810
  file_count: files.length,
793
811
  total_bytes: totalSize,
794
812
  include_memory_db: !!opts.includeMemoryDb,
813
+ include_sessions: !!opts.includeSessions,
795
814
  type: "local",
796
815
  trigger: opts.scheduled ? "scheduled" : "manual",
797
816
  rotated_count: rotatedCount
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawon",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Backup and restore your OpenClaw workspace",
5
5
  "type": "module",
6
6
  "bin": {