clawon 0.1.11 → 0.1.13
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 +22 -4
- package/dist/index.js +162 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,9 +56,27 @@ npx clawon schedule off
|
|
|
56
56
|
npx clawon schedule status
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
### Workspaces
|
|
60
|
+
|
|
61
|
+
Workspaces organize your cloud snapshots by machine or environment — like GitHub repos for your backups. A default workspace is created automatically on login.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# List your workspaces
|
|
65
|
+
npx clawon workspaces list
|
|
66
|
+
|
|
67
|
+
# Create a new workspace
|
|
68
|
+
npx clawon workspaces create "Work Server"
|
|
69
|
+
|
|
70
|
+
# Switch active workspace (affects backup/restore/list)
|
|
71
|
+
npx clawon workspaces switch work-server
|
|
72
|
+
|
|
73
|
+
# Show current workspace info
|
|
74
|
+
npx clawon workspaces info
|
|
75
|
+
```
|
|
76
|
+
|
|
59
77
|
### Cloud Backups (requires account)
|
|
60
78
|
|
|
61
|
-
Cloud backups sync your workspace to Clawon's servers for cross-machine access.
|
|
79
|
+
Cloud backups sync your workspace to Clawon's servers for cross-machine access. Snapshots are scoped to your current workspace.
|
|
62
80
|
|
|
63
81
|
```bash
|
|
64
82
|
# Authenticate (env var recommended to avoid shell history)
|
|
@@ -72,7 +90,7 @@ npx clawon login --api-key <your-key>
|
|
|
72
90
|
npx clawon backup
|
|
73
91
|
npx clawon backup --tag "stable config"
|
|
74
92
|
npx clawon backup --dry-run # Preview without uploading
|
|
75
|
-
npx clawon backup --include-memory-db # Requires Pro
|
|
93
|
+
npx clawon backup --include-memory-db # Requires Hobby or Pro
|
|
76
94
|
npx clawon backup --include-sessions # Requires Hobby or Pro
|
|
77
95
|
|
|
78
96
|
# List cloud backups
|
|
@@ -97,7 +115,7 @@ npx clawon discover # Show exactly which files would be backed up
|
|
|
97
115
|
npx clawon discover --include-memory-db # Include SQLite memory index
|
|
98
116
|
npx clawon discover --include-sessions # Include chat history
|
|
99
117
|
npx clawon schedule status # Show active schedules
|
|
100
|
-
npx clawon status # Connection status and file count
|
|
118
|
+
npx clawon status # Connection status, workspace, and file count
|
|
101
119
|
npx clawon logout # Remove local credentials
|
|
102
120
|
```
|
|
103
121
|
|
|
@@ -169,7 +187,7 @@ Each archive contains:
|
|
|
169
187
|
|
|
170
188
|
## Configuration
|
|
171
189
|
|
|
172
|
-
Config is stored at `~/.clawon/config.json` after running `clawon login`. Contains your API key, profile ID, and API URL. Run `clawon logout` to remove it.
|
|
190
|
+
Config is stored at `~/.clawon/config.json` after running `clawon login`. Contains your API key, profile ID, workspace, and API URL. Run `clawon logout` to remove it.
|
|
173
191
|
|
|
174
192
|
## Telemetry
|
|
175
193
|
|
package/dist/index.js
CHANGED
|
@@ -255,12 +255,20 @@ program.command("login").description("Connect to Clawon with your API key").opti
|
|
|
255
255
|
writeConfig({
|
|
256
256
|
apiKey,
|
|
257
257
|
profileId: connectJson.profileId,
|
|
258
|
+
workspaceId: connectJson.workspaceId || void 0,
|
|
259
|
+
workspaceSlug: connectJson.workspaceSlug || void 0,
|
|
258
260
|
apiBaseUrl: opts.apiUrl,
|
|
259
261
|
connectedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
260
262
|
});
|
|
261
263
|
console.log("\u2713 Logged in");
|
|
262
264
|
console.log(` Profile ID: ${connectJson.profileId}`);
|
|
263
|
-
|
|
265
|
+
if (connectJson.workspaceSlug) {
|
|
266
|
+
console.log(` Workspace: ${connectJson.workspaceSlug}`);
|
|
267
|
+
}
|
|
268
|
+
trackCliEvent(connectJson.profileId, "cli_login", {
|
|
269
|
+
workspace_slug: connectJson.workspaceSlug,
|
|
270
|
+
workspace_count: connectJson.workspaceCount ?? 1
|
|
271
|
+
});
|
|
264
272
|
} catch (e) {
|
|
265
273
|
console.error(`\u2717 Login failed: ${e.message}`);
|
|
266
274
|
process.exit(1);
|
|
@@ -268,7 +276,7 @@ program.command("login").description("Connect to Clawon with your API key").opti
|
|
|
268
276
|
});
|
|
269
277
|
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) => {
|
|
270
278
|
if (opts.includeMemoryDb) {
|
|
271
|
-
console.error("\u2717 Memory DB cloud backup requires a Pro account. Use `clawon local backup --include-memory-db` for local backups.");
|
|
279
|
+
console.error("\u2717 Memory DB cloud backup requires a Hobby or Pro account. Use `clawon local backup --include-memory-db` for local backups.");
|
|
272
280
|
process.exit(1);
|
|
273
281
|
}
|
|
274
282
|
if (opts.includeSessions) {
|
|
@@ -280,6 +288,11 @@ program.command("backup").description("Backup your OpenClaw workspace to the clo
|
|
|
280
288
|
console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
|
|
281
289
|
process.exit(1);
|
|
282
290
|
}
|
|
291
|
+
if (!cfg.workspaceId) {
|
|
292
|
+
console.error("\u2717 No workspace selected. Run: clawon workspaces switch <slug>");
|
|
293
|
+
console.error(" Or re-login: clawon login --api-key <key>");
|
|
294
|
+
process.exit(1);
|
|
295
|
+
}
|
|
283
296
|
if (!fs.existsSync(OPENCLAW_DIR)) {
|
|
284
297
|
console.error(`\u2717 OpenClaw directory not found: ${OPENCLAW_DIR}`);
|
|
285
298
|
process.exit(1);
|
|
@@ -314,6 +327,7 @@ program.command("backup").description("Backup your OpenClaw workspace to the clo
|
|
|
314
327
|
cfg.apiKey,
|
|
315
328
|
{
|
|
316
329
|
profileId: cfg.profileId,
|
|
330
|
+
workspaceId: cfg.workspaceId,
|
|
317
331
|
files: files.map((f) => ({ path: f.path, size: f.size })),
|
|
318
332
|
...opts.tag ? { tag: opts.tag } : {}
|
|
319
333
|
}
|
|
@@ -350,6 +364,7 @@ program.command("backup").description("Backup your OpenClaw workspace to the clo
|
|
|
350
364
|
include_memory_db: !!opts.includeMemoryDb,
|
|
351
365
|
include_sessions: !!opts.includeSessions,
|
|
352
366
|
type: "cloud",
|
|
367
|
+
workspace_slug: cfg.workspaceSlug,
|
|
353
368
|
trigger: opts.scheduled ? "scheduled" : "manual"
|
|
354
369
|
});
|
|
355
370
|
} catch (e) {
|
|
@@ -434,9 +449,10 @@ program.command("list").description("List your backups").option("--limit <n>", "
|
|
|
434
449
|
process.exit(1);
|
|
435
450
|
}
|
|
436
451
|
try {
|
|
452
|
+
const wsParam = cfg.workspaceId ? `&workspaceId=${cfg.workspaceId}` : "";
|
|
437
453
|
const { snapshots } = await api(
|
|
438
454
|
cfg.apiBaseUrl,
|
|
439
|
-
`/api/v1/snapshots/list?profileId=${cfg.profileId}&limit=${opts.limit}`,
|
|
455
|
+
`/api/v1/snapshots/list?profileId=${cfg.profileId}&limit=${opts.limit}${wsParam}`,
|
|
440
456
|
"GET",
|
|
441
457
|
cfg.apiKey
|
|
442
458
|
);
|
|
@@ -444,6 +460,10 @@ program.command("list").description("List your backups").option("--limit <n>", "
|
|
|
444
460
|
console.log("No backups yet. Run: clawon backup");
|
|
445
461
|
return;
|
|
446
462
|
}
|
|
463
|
+
if (cfg.workspaceSlug) {
|
|
464
|
+
console.log(`Workspace: ${cfg.workspaceSlug}
|
|
465
|
+
`);
|
|
466
|
+
}
|
|
447
467
|
console.log("Your backups:\n");
|
|
448
468
|
console.log("ID | Date | Files | Size | Tag");
|
|
449
469
|
console.log("\u2500".repeat(100));
|
|
@@ -916,12 +936,151 @@ local.command("restore").description("Restore from a local backup").option("--fi
|
|
|
916
936
|
process.exit(1);
|
|
917
937
|
}
|
|
918
938
|
});
|
|
939
|
+
var workspaces = program.command("workspaces").description("Manage workspaces");
|
|
940
|
+
workspaces.command("list").description("List your workspaces").action(async () => {
|
|
941
|
+
const cfg = readConfig();
|
|
942
|
+
if (!cfg) {
|
|
943
|
+
console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
|
|
944
|
+
process.exit(1);
|
|
945
|
+
}
|
|
946
|
+
try {
|
|
947
|
+
const { workspaces: wsList } = await api(
|
|
948
|
+
cfg.apiBaseUrl,
|
|
949
|
+
`/api/v1/workspaces/list?profileId=${cfg.profileId}`,
|
|
950
|
+
"GET",
|
|
951
|
+
cfg.apiKey
|
|
952
|
+
);
|
|
953
|
+
if (!wsList?.length) {
|
|
954
|
+
console.log("No workspaces yet.");
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
console.log("Your workspaces:\n");
|
|
958
|
+
console.log("Name | Slug | Snapshots | Last Backup");
|
|
959
|
+
console.log("\u2500".repeat(80));
|
|
960
|
+
for (const ws of wsList) {
|
|
961
|
+
const lastBackup = ws.lastBackupAt ? new Date(ws.lastBackupAt).toLocaleString() : "Never";
|
|
962
|
+
const current = ws.id === cfg.workspaceId ? " \u2190 current" : "";
|
|
963
|
+
console.log(
|
|
964
|
+
`${ws.name.padEnd(20)} | ${ws.slug.padEnd(20)} | ${String(ws.snapshotCount).padEnd(9)} | ${lastBackup}${current}`
|
|
965
|
+
);
|
|
966
|
+
}
|
|
967
|
+
console.log(`
|
|
968
|
+
Total: ${wsList.length} workspace(s)`);
|
|
969
|
+
trackCliEvent(cfg.profileId, "cli_workspaces_listed", { count: wsList.length });
|
|
970
|
+
} catch (e) {
|
|
971
|
+
console.error(`\u2717 Failed to list workspaces: ${e.message}`);
|
|
972
|
+
process.exit(1);
|
|
973
|
+
}
|
|
974
|
+
});
|
|
975
|
+
workspaces.command("create <name>").description("Create a new workspace").option("--description <desc>", "Workspace description").action(async (name, opts) => {
|
|
976
|
+
const cfg = readConfig();
|
|
977
|
+
if (!cfg) {
|
|
978
|
+
console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
|
|
979
|
+
process.exit(1);
|
|
980
|
+
}
|
|
981
|
+
try {
|
|
982
|
+
const { workspace } = await api(
|
|
983
|
+
cfg.apiBaseUrl,
|
|
984
|
+
"/api/v1/workspaces/create",
|
|
985
|
+
"POST",
|
|
986
|
+
cfg.apiKey,
|
|
987
|
+
{
|
|
988
|
+
profileId: cfg.profileId,
|
|
989
|
+
name,
|
|
990
|
+
...opts.description ? { description: opts.description } : {}
|
|
991
|
+
}
|
|
992
|
+
);
|
|
993
|
+
console.log(`\u2713 Workspace created`);
|
|
994
|
+
console.log(` Name: ${workspace.name}`);
|
|
995
|
+
console.log(` Slug: ${workspace.slug}`);
|
|
996
|
+
console.log(`
|
|
997
|
+
Switch to it: clawon workspaces switch ${workspace.slug}`);
|
|
998
|
+
trackCliEvent(cfg.profileId, "workspace_created", { name, slug: workspace.slug });
|
|
999
|
+
} catch (e) {
|
|
1000
|
+
console.error(`\u2717 Failed to create workspace: ${e.message}`);
|
|
1001
|
+
process.exit(1);
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
workspaces.command("switch <slug>").description("Switch to a different workspace").action(async (slug) => {
|
|
1005
|
+
const cfg = readConfig();
|
|
1006
|
+
if (!cfg) {
|
|
1007
|
+
console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
|
|
1008
|
+
process.exit(1);
|
|
1009
|
+
}
|
|
1010
|
+
try {
|
|
1011
|
+
const { workspaces: wsList } = await api(
|
|
1012
|
+
cfg.apiBaseUrl,
|
|
1013
|
+
`/api/v1/workspaces/list?profileId=${cfg.profileId}`,
|
|
1014
|
+
"GET",
|
|
1015
|
+
cfg.apiKey
|
|
1016
|
+
);
|
|
1017
|
+
const target = (wsList || []).find((w) => w.slug === slug);
|
|
1018
|
+
if (!target) {
|
|
1019
|
+
console.error(`\u2717 Workspace "${slug}" not found.`);
|
|
1020
|
+
console.error(" Available workspaces:");
|
|
1021
|
+
for (const ws of wsList || []) {
|
|
1022
|
+
console.error(` \u2022 ${ws.slug}`);
|
|
1023
|
+
}
|
|
1024
|
+
process.exit(1);
|
|
1025
|
+
}
|
|
1026
|
+
const previousSlug = cfg.workspaceSlug;
|
|
1027
|
+
updateConfig({ workspaceId: target.id, workspaceSlug: target.slug });
|
|
1028
|
+
console.log(`\u2713 Switched to workspace: ${target.name} (${target.slug})`);
|
|
1029
|
+
trackCliEvent(cfg.profileId, "workspace_switched", {
|
|
1030
|
+
from_slug: previousSlug,
|
|
1031
|
+
to_slug: target.slug
|
|
1032
|
+
});
|
|
1033
|
+
} catch (e) {
|
|
1034
|
+
console.error(`\u2717 Failed to switch workspace: ${e.message}`);
|
|
1035
|
+
process.exit(1);
|
|
1036
|
+
}
|
|
1037
|
+
});
|
|
1038
|
+
workspaces.command("info").description("Show current workspace info").action(async () => {
|
|
1039
|
+
const cfg = readConfig();
|
|
1040
|
+
if (!cfg) {
|
|
1041
|
+
console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
|
|
1042
|
+
process.exit(1);
|
|
1043
|
+
}
|
|
1044
|
+
if (!cfg.workspaceId) {
|
|
1045
|
+
console.log("No workspace selected. Run: clawon workspaces switch <slug>");
|
|
1046
|
+
return;
|
|
1047
|
+
}
|
|
1048
|
+
try {
|
|
1049
|
+
const { workspaces: wsList } = await api(
|
|
1050
|
+
cfg.apiBaseUrl,
|
|
1051
|
+
`/api/v1/workspaces/list?profileId=${cfg.profileId}`,
|
|
1052
|
+
"GET",
|
|
1053
|
+
cfg.apiKey
|
|
1054
|
+
);
|
|
1055
|
+
const current = (wsList || []).find((w) => w.id === cfg.workspaceId);
|
|
1056
|
+
if (!current) {
|
|
1057
|
+
console.log("Current workspace not found on server. It may have been deleted.");
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
console.log("Current Workspace\n");
|
|
1061
|
+
console.log(` Name: ${current.name}`);
|
|
1062
|
+
console.log(` Slug: ${current.slug}`);
|
|
1063
|
+
console.log(` Snapshots: ${current.snapshotCount}`);
|
|
1064
|
+
if (current.lastBackupAt) {
|
|
1065
|
+
console.log(` Last backup: ${new Date(current.lastBackupAt).toLocaleString()}`);
|
|
1066
|
+
}
|
|
1067
|
+
if (current.description) {
|
|
1068
|
+
console.log(` Description: ${current.description}`);
|
|
1069
|
+
}
|
|
1070
|
+
} catch (e) {
|
|
1071
|
+
console.error(`\u2717 Failed to get workspace info: ${e.message}`);
|
|
1072
|
+
process.exit(1);
|
|
1073
|
+
}
|
|
1074
|
+
});
|
|
919
1075
|
program.command("status").description("Show current status").action(async () => {
|
|
920
1076
|
const cfg = readConfig();
|
|
921
1077
|
console.log("Clawon Status\n");
|
|
922
1078
|
if (cfg) {
|
|
923
1079
|
console.log(`\u2713 Logged in`);
|
|
924
1080
|
console.log(` Profile ID: ${cfg.profileId}`);
|
|
1081
|
+
if (cfg.workspaceSlug) {
|
|
1082
|
+
console.log(` Workspace: ${cfg.workspaceSlug}`);
|
|
1083
|
+
}
|
|
925
1084
|
console.log(` API: ${cfg.apiBaseUrl}`);
|
|
926
1085
|
} else {
|
|
927
1086
|
console.log(`\u2717 Not logged in`);
|