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.
- package/README.md +10 -2
- package/dist/index.js +38 -19
- 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
|
|
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").
|
|
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",
|
|
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
|
|
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
|