clawon 0.1.16 → 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.
- package/README.md +28 -3
- package/dist/index.js +51 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -23,6 +23,8 @@ 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
|
|
27
|
+
npx clawon local backup --no-secret-scan # Skip secret scanning
|
|
26
28
|
npx clawon local backup --max-snapshots 10 # Keep only 10 most recent
|
|
27
29
|
|
|
28
30
|
# List all local backups
|
|
@@ -44,6 +46,7 @@ npx clawon local schedule on
|
|
|
44
46
|
npx clawon local schedule on --every 6h --max-snapshots 10
|
|
45
47
|
npx clawon local schedule on --include-memory-db
|
|
46
48
|
npx clawon local schedule on --include-sessions
|
|
49
|
+
npx clawon local schedule on --include-secrets
|
|
47
50
|
|
|
48
51
|
# Disable local schedule
|
|
49
52
|
npx clawon local schedule off
|
|
@@ -92,6 +95,7 @@ npx clawon backup --tag "stable config"
|
|
|
92
95
|
npx clawon backup --dry-run # Preview without uploading
|
|
93
96
|
npx clawon backup --include-memory-db # Requires Hobby or Pro
|
|
94
97
|
npx clawon backup --include-sessions # Requires Hobby or Pro
|
|
98
|
+
npx clawon backup --no-secret-scan # Skip secret scanning
|
|
95
99
|
|
|
96
100
|
# List cloud backups
|
|
97
101
|
npx clawon list
|
|
@@ -114,6 +118,8 @@ npx clawon activity # Recent events
|
|
|
114
118
|
npx clawon discover # Show exactly which files would be backed up
|
|
115
119
|
npx clawon discover --include-memory-db # Include SQLite memory index
|
|
116
120
|
npx clawon discover --include-sessions # Include chat history
|
|
121
|
+
npx clawon discover --include-secrets # Preview with credentials included
|
|
122
|
+
npx clawon discover --scan # Scan for secrets in discovered files
|
|
117
123
|
npx clawon schedule status # Show active schedules
|
|
118
124
|
npx clawon status # Connection status, workspace, and file count
|
|
119
125
|
npx clawon logout # Remove local credentials
|
|
@@ -146,15 +152,34 @@ These are **always excluded**, even if they match an include pattern:
|
|
|
146
152
|
|---------|-----|
|
|
147
153
|
| `credentials/**` | API keys, tokens, auth files |
|
|
148
154
|
| `openclaw.json` | May contain credentials |
|
|
149
|
-
| `agents/*/auth.json` | Authentication data |
|
|
150
|
-
| `agents/*/auth-profiles.json` | Auth profiles |
|
|
155
|
+
| `agents/*/agent/auth.json` | Authentication data |
|
|
156
|
+
| `agents/*/agent/auth-profiles.json` | Auth profiles |
|
|
151
157
|
| `agents/*/sessions/**` | Chat history (large, use `--include-sessions` to include) |
|
|
152
158
|
| `memory/lancedb/**` | Vector database (binary, large) |
|
|
153
159
|
| `memory/*.sqlite` | SQLite databases (use `--include-memory-db` to include) |
|
|
154
160
|
| `*.lock`, `*.wal`, `*.shm` | Database lock files |
|
|
155
161
|
| `node_modules/**` | Dependencies |
|
|
156
162
|
|
|
157
|
-
**Credentials
|
|
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.
|
|
164
|
+
|
|
165
|
+
## Secret Scanning
|
|
166
|
+
|
|
167
|
+
Every backup is pre-scanned for leaked secrets using **221 detection rules** ported from [gitleaks](https://github.com/gitleaks/gitleaks). This catches API keys, tokens, private keys, JWTs, and more — before they leave your machine.
|
|
168
|
+
|
|
169
|
+
How it works: keyword pre-filtering narrows candidates, then regex matching and Shannon entropy checks confirm real secrets. No new dependencies — pure regex matching built into the CLI.
|
|
170
|
+
|
|
171
|
+
When secrets are found during a manual backup, you'll see an interactive prompt:
|
|
172
|
+
- `[s]` — **Skip** flagged files (default)
|
|
173
|
+
- `[a]` — **Abort** the backup entirely
|
|
174
|
+
- `[i]` — **Ignore** findings and back up anyway
|
|
175
|
+
|
|
176
|
+
Scheduled backups automatically skip flagged files.
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
npx clawon discover --scan # Preview secret findings without backing up
|
|
180
|
+
npx clawon local backup --no-secret-scan # Disable scanning for a backup
|
|
181
|
+
npx clawon backup --no-secret-scan # Same for cloud backups
|
|
182
|
+
```
|
|
158
183
|
|
|
159
184
|
## Archive Format
|
|
160
185
|
|
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
|
-
|
|
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,
|