clawon 0.1.17 → 0.1.18

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 +6 -3
  2. package/dist/index.js +51 -18
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -23,6 +23,7 @@ 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
25
  npx clawon local backup --include-sessions # Include chat history
26
+ npx clawon local backup --include-secrets # Include credentials and auth files
26
27
  npx clawon local backup --no-secret-scan # Skip secret scanning
27
28
  npx clawon local backup --max-snapshots 10 # Keep only 10 most recent
28
29
 
@@ -45,6 +46,7 @@ npx clawon local schedule on
45
46
  npx clawon local schedule on --every 6h --max-snapshots 10
46
47
  npx clawon local schedule on --include-memory-db
47
48
  npx clawon local schedule on --include-sessions
49
+ npx clawon local schedule on --include-secrets
48
50
 
49
51
  # Disable local schedule
50
52
  npx clawon local schedule off
@@ -116,6 +118,7 @@ npx clawon activity # Recent events
116
118
  npx clawon discover # Show exactly which files would be backed up
117
119
  npx clawon discover --include-memory-db # Include SQLite memory index
118
120
  npx clawon discover --include-sessions # Include chat history
121
+ npx clawon discover --include-secrets # Preview with credentials included
119
122
  npx clawon discover --scan # Scan for secrets in discovered files
120
123
  npx clawon schedule status # Show active schedules
121
124
  npx clawon status # Connection status, workspace, and file count
@@ -149,15 +152,15 @@ These are **always excluded**, even if they match an include pattern:
149
152
  |---------|-----|
150
153
  | `credentials/**` | API keys, tokens, auth files |
151
154
  | `openclaw.json` | May contain credentials |
152
- | `agents/*/auth.json` | Authentication data |
153
- | `agents/*/auth-profiles.json` | Auth profiles |
155
+ | `agents/*/agent/auth.json` | Authentication data |
156
+ | `agents/*/agent/auth-profiles.json` | Auth profiles |
154
157
  | `agents/*/sessions/**` | Chat history (large, use `--include-sessions` to include) |
155
158
  | `memory/lancedb/**` | Vector database (binary, large) |
156
159
  | `memory/*.sqlite` | SQLite databases (use `--include-memory-db` to include) |
157
160
  | `*.lock`, `*.wal`, `*.shm` | Database lock files |
158
161
  | `node_modules/**` | Dependencies |
159
162
 
160
- **Credentials never leave your machine.** The entire `credentials/` directory and `openclaw.json` are excluded by default. You can verify this by running `npx clawon discover` before any backup.
163
+ **Credentials are excluded by default.** The `credentials/` directory, `openclaw.json`, and agent auth files are excluded unless you use `--include-secrets` (local backups only). You can verify what gets included by running `npx clawon discover` (or `npx clawon discover --include-secrets`) before any backup.
161
164
 
162
165
  ## Secret Scanning
163
166
 
package/dist/index.js CHANGED
@@ -4708,8 +4708,8 @@ var INCLUDE_PATTERNS = [
4708
4708
  var EXCLUDE_PATTERNS = [
4709
4709
  "credentials/**",
4710
4710
  "openclaw.json",
4711
- "agents/*/auth.json",
4712
- "agents/*/auth-profiles.json",
4711
+ "agents/*/agent/auth.json",
4712
+ "agents/*/agent/auth-profiles.json",
4713
4713
  "agents/*/sessions/**",
4714
4714
  "memory/lancedb/**",
4715
4715
  "memory/*.sqlite",
@@ -4725,13 +4725,24 @@ function matchGlob(filePath, pattern) {
4725
4725
  let regexPattern = pattern.replace(/\./g, "\\.").replace(/\*\*\//g, "(.*/)?").replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*");
4726
4726
  return new RegExp(`^${regexPattern}$`).test(filePath);
4727
4727
  }
4728
- function shouldInclude(relativePath, includeMemoryDb = false, includeSessions = false) {
4728
+ var SECRET_PATTERNS = [
4729
+ "credentials/**",
4730
+ "openclaw.json",
4731
+ "agents/*/agent/auth.json",
4732
+ "agents/*/agent/auth-profiles.json"
4733
+ ];
4734
+ function shouldInclude(relativePath, includeMemoryDb = false, includeSessions = false, includeSecrets = false) {
4729
4735
  if (includeMemoryDb && matchGlob(relativePath, "memory/*.sqlite")) {
4730
4736
  return true;
4731
4737
  }
4732
4738
  if (includeSessions && matchGlob(relativePath, "agents/*/sessions/**")) {
4733
4739
  return true;
4734
4740
  }
4741
+ if (includeSecrets) {
4742
+ for (const pattern of SECRET_PATTERNS) {
4743
+ if (matchGlob(relativePath, pattern)) return true;
4744
+ }
4745
+ }
4735
4746
  for (const pattern of EXCLUDE_PATTERNS) {
4736
4747
  if (matchGlob(relativePath, pattern)) return false;
4737
4748
  }
@@ -4740,7 +4751,7 @@ function shouldInclude(relativePath, includeMemoryDb = false, includeSessions =
4740
4751
  }
4741
4752
  return false;
4742
4753
  }
4743
- function discoverFiles(baseDir, includeMemoryDb = false, includeSessions = false) {
4754
+ function discoverFiles(baseDir, includeMemoryDb = false, includeSessions = false, includeSecrets = false) {
4744
4755
  const files = [];
4745
4756
  function walk(dir, relativePath = "") {
4746
4757
  if (!fs2.existsSync(dir)) return;
@@ -4751,7 +4762,7 @@ function discoverFiles(baseDir, includeMemoryDb = false, includeSessions = false
4751
4762
  if (entry.isDirectory()) {
4752
4763
  walk(fullPath, relPath);
4753
4764
  } else if (entry.isFile()) {
4754
- if (shouldInclude(relPath, includeMemoryDb, includeSessions)) {
4765
+ if (shouldInclude(relPath, includeMemoryDb, includeSessions, includeSecrets)) {
4755
4766
  const stats = fs2.statSync(fullPath);
4756
4767
  files.push({
4757
4768
  path: relPath,
@@ -4764,7 +4775,7 @@ function discoverFiles(baseDir, includeMemoryDb = false, includeSessions = false
4764
4775
  walk(baseDir);
4765
4776
  return files;
4766
4777
  }
4767
- async function createLocalArchive(files, openclawDir, outputPath, tag, includeMemoryDb, includeSessions, trigger) {
4778
+ async function createLocalArchive(files, openclawDir, outputPath, tag, includeMemoryDb, includeSessions, includeSecrets, trigger) {
4768
4779
  const meta = {
4769
4780
  version: 2,
4770
4781
  created: (/* @__PURE__ */ new Date()).toISOString(),
@@ -4772,6 +4783,7 @@ async function createLocalArchive(files, openclawDir, outputPath, tag, includeMe
4772
4783
  file_count: files.length,
4773
4784
  ...includeMemoryDb ? { include_memory_db: true } : {},
4774
4785
  ...includeSessions ? { include_sessions: true } : {},
4786
+ ...includeSecrets ? { include_secrets: true } : {},
4775
4787
  ...trigger ? { trigger } : {}
4776
4788
  };
4777
4789
  const metaPath = path2.join(openclawDir, "_clawon_meta.json");
@@ -4941,7 +4953,11 @@ program.command("login").description("Connect to Clawon with your API key").opti
4941
4953
  process.exit(1);
4942
4954
  }
4943
4955
  });
4944
- 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)").option("--no-secret-scan", "Skip secret scanning before backup").action(async (opts) => {
4956
+ 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("--include-secrets", "Include credentials and auth files in backup").option("--scheduled", "Internal: triggered by cron (suppresses interactive output)").option("--no-secret-scan", "Skip secret scanning before backup").action(async (opts) => {
4957
+ if (opts.includeSecrets) {
4958
+ console.error("--include-secrets is not supported for cloud backups yet. Use local backups, or wait for --encrypt support.");
4959
+ process.exit(1);
4960
+ }
4945
4961
  const cfg = readConfig();
4946
4962
  if (!cfg) {
4947
4963
  console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
@@ -5275,12 +5291,12 @@ program.command("delete [id]").description("Delete a snapshot").option("--oldest
5275
5291
  process.exit(1);
5276
5292
  }
5277
5293
  });
5278
- 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)").option("--scan", "Run secret scanning on discovered files").action(async (opts) => {
5294
+ 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)").option("--include-secrets", "Include credentials and auth files").option("--scan", "Run secret scanning on discovered files").action(async (opts) => {
5279
5295
  if (!fs2.existsSync(OPENCLAW_DIR)) {
5280
5296
  console.error(`\u2717 OpenClaw directory not found: ${OPENCLAW_DIR}`);
5281
5297
  process.exit(1);
5282
5298
  }
5283
- const files = discoverFiles(OPENCLAW_DIR, !!opts.includeMemoryDb, !!opts.includeSessions);
5299
+ const files = discoverFiles(OPENCLAW_DIR, !!opts.includeMemoryDb, !!opts.includeSessions, !!opts.includeSecrets);
5284
5300
  if (files.length === 0) {
5285
5301
  console.log("No files matched the include patterns.");
5286
5302
  return;
@@ -5315,7 +5331,7 @@ Total: ${files.length} files (${(totalSize / 1024).toFixed(1)} KB)`);
5315
5331
  console.log(` Scanned ${scanResult.filesScanned} files in ${scanResult.durationMs}ms (${scanResult.rulesLoaded} rules loaded)`);
5316
5332
  }
5317
5333
  const cfg = readConfig();
5318
- trackCliEvent(cfg?.profileId || "anonymous", "cli_discover", { file_count: files.length, include_memory_db: !!opts.includeMemoryDb, include_sessions: !!opts.includeSessions });
5334
+ trackCliEvent(cfg?.profileId || "anonymous", "cli_discover", { file_count: files.length, include_memory_db: !!opts.includeMemoryDb, include_sessions: !!opts.includeSessions, include_secrets: !!opts.includeSecrets });
5319
5335
  });
5320
5336
  var schedule = program.command("schedule").description("Manage scheduled cloud backups");
5321
5337
  schedule.command("on").description("Enable scheduled cloud backups via cron").option("--every <interval>", "Backup interval: 1h, 6h, 12h, 24h", "12h").action(async (opts) => {
@@ -5462,7 +5478,7 @@ Total: ${files.length} files`);
5462
5478
  });
5463
5479
  var local = program.command("local").description("Local backup and restore (no cloud required)");
5464
5480
  var localSchedule = local.command("schedule").description("Manage scheduled local backups");
5465
- 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) => {
5481
+ 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)").option("--include-secrets", "Include credentials and auth files in backup").action(async (opts) => {
5466
5482
  assertNotWindows();
5467
5483
  const interval = opts.every;
5468
5484
  if (!VALID_INTERVALS.includes(interval)) {
@@ -5472,7 +5488,7 @@ localSchedule.command("on").description("Enable scheduled local backups via cron
5472
5488
  const cfg = readConfig();
5473
5489
  const wasEnabled = cfg?.schedule?.local?.enabled;
5474
5490
  const cronExpr = INTERVAL_CRON[interval];
5475
- const args = "local backup --scheduled" + (opts.includeMemoryDb ? " --include-memory-db" : "") + (opts.includeSessions ? " --include-sessions" : "") + (opts.maxSnapshots ? ` --max-snapshots ${opts.maxSnapshots}` : "");
5491
+ const args = "local backup --scheduled" + (opts.includeMemoryDb ? " --include-memory-db" : "") + (opts.includeSessions ? " --include-sessions" : "") + (opts.includeSecrets ? " --include-secrets" : "") + (opts.maxSnapshots ? ` --max-snapshots ${opts.maxSnapshots}` : "");
5476
5492
  const command = resolveCliCommand(args);
5477
5493
  addCronEntry(CRON_MARKER_LOCAL, cronExpr, command);
5478
5494
  const maxSnapshots = opts.maxSnapshots ? parseInt(opts.maxSnapshots, 10) : null;
@@ -5483,7 +5499,8 @@ localSchedule.command("on").description("Enable scheduled local backups via cron
5483
5499
  intervalHours: parseInt(interval),
5484
5500
  ...maxSnapshots ? { maxSnapshots } : {},
5485
5501
  ...opts.includeMemoryDb ? { includeMemoryDb: true } : {},
5486
- ...opts.includeSessions ? { includeSessions: true } : {}
5502
+ ...opts.includeSessions ? { includeSessions: true } : {},
5503
+ ...opts.includeSecrets ? { includeSecrets: true } : {}
5487
5504
  }
5488
5505
  }
5489
5506
  });
@@ -5492,8 +5509,9 @@ localSchedule.command("on").description("Enable scheduled local backups via cron
5492
5509
  if (maxSnapshots) console.log(` Max snapshots: ${maxSnapshots}`);
5493
5510
  if (opts.includeMemoryDb) console.log(` Memory DB: included`);
5494
5511
  if (opts.includeSessions) console.log(` Sessions: included`);
5512
+ if (opts.includeSecrets) console.log(` Secrets: included`);
5495
5513
  console.log(` Log: ${SCHEDULE_LOG}`);
5496
- const firstRunArgs = "local backup" + (opts.includeMemoryDb ? " --include-memory-db" : "") + (opts.includeSessions ? " --include-sessions" : "") + (opts.maxSnapshots ? ` --max-snapshots ${opts.maxSnapshots}` : "");
5514
+ const firstRunArgs = "local backup" + (opts.includeMemoryDb ? " --include-memory-db" : "") + (opts.includeSessions ? " --include-sessions" : "") + (opts.includeSecrets ? " --include-secrets" : "") + (opts.maxSnapshots ? ` --max-snapshots ${opts.maxSnapshots}` : "");
5497
5515
  console.log("\nRunning first backup now...\n");
5498
5516
  try {
5499
5517
  execSync(resolveCliCommand(firstRunArgs), { stdio: "inherit" });
@@ -5505,7 +5523,8 @@ localSchedule.command("on").description("Enable scheduled local backups via cron
5505
5523
  interval_hours: parseInt(interval),
5506
5524
  max_snapshots: maxSnapshots,
5507
5525
  include_memory_db: !!opts.includeMemoryDb,
5508
- include_sessions: !!opts.includeSessions
5526
+ include_sessions: !!opts.includeSessions,
5527
+ include_secrets: !!opts.includeSecrets
5509
5528
  });
5510
5529
  });
5511
5530
  localSchedule.command("off").description("Disable scheduled local backups").action(async () => {
@@ -5524,18 +5543,31 @@ localSchedule.command("off").description("Disable scheduled local backups").acti
5524
5543
  const cfg = readConfig();
5525
5544
  trackCliEvent(cfg?.profileId || "anonymous", "schedule_disabled", { type: "local" });
5526
5545
  });
5527
- 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("--no-secret-scan", "Skip secret scanning before backup").option("--max-snapshots <n>", "Keep only the N most recent local backups").action(async (opts) => {
5546
+ 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("--include-secrets", "Include credentials and auth files in backup").option("--scheduled", "Internal: triggered by cron (suppresses interactive output)").option("--no-secret-scan", "Skip secret scanning before backup").option("--max-snapshots <n>", "Keep only the N most recent local backups").action(async (opts) => {
5528
5547
  if (!fs2.existsSync(OPENCLAW_DIR)) {
5529
5548
  console.error(`\u2717 OpenClaw directory not found: ${OPENCLAW_DIR}`);
5530
5549
  process.exit(1);
5531
5550
  }
5532
5551
  try {
5533
5552
  if (!opts.scheduled) console.log("Discovering files...");
5534
- let files = discoverFiles(OPENCLAW_DIR, !!opts.includeMemoryDb, !!opts.includeSessions);
5553
+ let files = discoverFiles(OPENCLAW_DIR, !!opts.includeMemoryDb, !!opts.includeSessions, !!opts.includeSecrets);
5535
5554
  if (files.length === 0) {
5536
5555
  console.error("\u2717 No files found to backup");
5537
5556
  process.exit(1);
5538
5557
  }
5558
+ if (opts.includeSecrets && !opts.scheduled) {
5559
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
5560
+ const confirmed = await new Promise((resolve) => {
5561
+ rl.question("\u26A0 --include-secrets will back up API keys, tokens, and auth files. Continue? [y/N] ", (answer) => {
5562
+ rl.close();
5563
+ resolve(answer.trim().toLowerCase() === "y");
5564
+ });
5565
+ });
5566
+ if (!confirmed) {
5567
+ console.log("Backup aborted.");
5568
+ process.exit(0);
5569
+ }
5570
+ }
5539
5571
  let secretsFound = 0;
5540
5572
  let secretsFilesSkipped = 0;
5541
5573
  const scanSkipped = !opts.secretScan;
@@ -5575,7 +5607,7 @@ local.command("backup").description("Save a local backup of your OpenClaw worksp
5575
5607
  const filename = `backup-${timestamp}.tar.gz`;
5576
5608
  const filePath = path2.join(BACKUPS_DIR, filename);
5577
5609
  if (!opts.scheduled) console.log("Creating archive...");
5578
- await createLocalArchive(files, OPENCLAW_DIR, filePath, opts.tag, opts.includeMemoryDb, opts.includeSessions, opts.scheduled ? "scheduled" : "manual");
5610
+ await createLocalArchive(files, OPENCLAW_DIR, filePath, opts.tag, opts.includeMemoryDb, opts.includeSessions, opts.includeSecrets, opts.scheduled ? "scheduled" : "manual");
5579
5611
  const archiveSize = fs2.statSync(filePath).size;
5580
5612
  if (!opts.scheduled) {
5581
5613
  console.log(`
@@ -5606,6 +5638,7 @@ local.command("backup").description("Save a local backup of your OpenClaw worksp
5606
5638
  total_bytes: totalSize,
5607
5639
  include_memory_db: !!opts.includeMemoryDb,
5608
5640
  include_sessions: !!opts.includeSessions,
5641
+ include_secrets: !!opts.includeSecrets,
5609
5642
  type: "local",
5610
5643
  trigger: opts.scheduled ? "scheduled" : "manual",
5611
5644
  rotated_count: rotatedCount,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawon",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "Backup and restore your OpenClaw workspace",
5
5
  "type": "module",
6
6
  "bin": {