clawon 0.1.11 → 0.1.12
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 +161 -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,19 @@ 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
|
+
});
|
|
264
271
|
} catch (e) {
|
|
265
272
|
console.error(`\u2717 Login failed: ${e.message}`);
|
|
266
273
|
process.exit(1);
|
|
@@ -268,7 +275,7 @@ program.command("login").description("Connect to Clawon with your API key").opti
|
|
|
268
275
|
});
|
|
269
276
|
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
277
|
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.");
|
|
278
|
+
console.error("\u2717 Memory DB cloud backup requires a Hobby or Pro account. Use `clawon local backup --include-memory-db` for local backups.");
|
|
272
279
|
process.exit(1);
|
|
273
280
|
}
|
|
274
281
|
if (opts.includeSessions) {
|
|
@@ -280,6 +287,11 @@ program.command("backup").description("Backup your OpenClaw workspace to the clo
|
|
|
280
287
|
console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
|
|
281
288
|
process.exit(1);
|
|
282
289
|
}
|
|
290
|
+
if (!cfg.workspaceId) {
|
|
291
|
+
console.error("\u2717 No workspace selected. Run: clawon workspaces switch <slug>");
|
|
292
|
+
console.error(" Or re-login: clawon login --api-key <key>");
|
|
293
|
+
process.exit(1);
|
|
294
|
+
}
|
|
283
295
|
if (!fs.existsSync(OPENCLAW_DIR)) {
|
|
284
296
|
console.error(`\u2717 OpenClaw directory not found: ${OPENCLAW_DIR}`);
|
|
285
297
|
process.exit(1);
|
|
@@ -314,6 +326,7 @@ program.command("backup").description("Backup your OpenClaw workspace to the clo
|
|
|
314
326
|
cfg.apiKey,
|
|
315
327
|
{
|
|
316
328
|
profileId: cfg.profileId,
|
|
329
|
+
workspaceId: cfg.workspaceId,
|
|
317
330
|
files: files.map((f) => ({ path: f.path, size: f.size })),
|
|
318
331
|
...opts.tag ? { tag: opts.tag } : {}
|
|
319
332
|
}
|
|
@@ -350,6 +363,7 @@ program.command("backup").description("Backup your OpenClaw workspace to the clo
|
|
|
350
363
|
include_memory_db: !!opts.includeMemoryDb,
|
|
351
364
|
include_sessions: !!opts.includeSessions,
|
|
352
365
|
type: "cloud",
|
|
366
|
+
workspace_slug: cfg.workspaceSlug,
|
|
353
367
|
trigger: opts.scheduled ? "scheduled" : "manual"
|
|
354
368
|
});
|
|
355
369
|
} catch (e) {
|
|
@@ -434,9 +448,10 @@ program.command("list").description("List your backups").option("--limit <n>", "
|
|
|
434
448
|
process.exit(1);
|
|
435
449
|
}
|
|
436
450
|
try {
|
|
451
|
+
const wsParam = cfg.workspaceId ? `&workspaceId=${cfg.workspaceId}` : "";
|
|
437
452
|
const { snapshots } = await api(
|
|
438
453
|
cfg.apiBaseUrl,
|
|
439
|
-
`/api/v1/snapshots/list?profileId=${cfg.profileId}&limit=${opts.limit}`,
|
|
454
|
+
`/api/v1/snapshots/list?profileId=${cfg.profileId}&limit=${opts.limit}${wsParam}`,
|
|
440
455
|
"GET",
|
|
441
456
|
cfg.apiKey
|
|
442
457
|
);
|
|
@@ -444,6 +459,10 @@ program.command("list").description("List your backups").option("--limit <n>", "
|
|
|
444
459
|
console.log("No backups yet. Run: clawon backup");
|
|
445
460
|
return;
|
|
446
461
|
}
|
|
462
|
+
if (cfg.workspaceSlug) {
|
|
463
|
+
console.log(`Workspace: ${cfg.workspaceSlug}
|
|
464
|
+
`);
|
|
465
|
+
}
|
|
447
466
|
console.log("Your backups:\n");
|
|
448
467
|
console.log("ID | Date | Files | Size | Tag");
|
|
449
468
|
console.log("\u2500".repeat(100));
|
|
@@ -916,12 +935,151 @@ local.command("restore").description("Restore from a local backup").option("--fi
|
|
|
916
935
|
process.exit(1);
|
|
917
936
|
}
|
|
918
937
|
});
|
|
938
|
+
var workspaces = program.command("workspaces").description("Manage workspaces");
|
|
939
|
+
workspaces.command("list").description("List your workspaces").action(async () => {
|
|
940
|
+
const cfg = readConfig();
|
|
941
|
+
if (!cfg) {
|
|
942
|
+
console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
|
|
943
|
+
process.exit(1);
|
|
944
|
+
}
|
|
945
|
+
try {
|
|
946
|
+
const { workspaces: wsList } = await api(
|
|
947
|
+
cfg.apiBaseUrl,
|
|
948
|
+
`/api/v1/workspaces/list?profileId=${cfg.profileId}`,
|
|
949
|
+
"GET",
|
|
950
|
+
cfg.apiKey
|
|
951
|
+
);
|
|
952
|
+
if (!wsList?.length) {
|
|
953
|
+
console.log("No workspaces yet.");
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
console.log("Your workspaces:\n");
|
|
957
|
+
console.log("Name | Slug | Snapshots | Last Backup");
|
|
958
|
+
console.log("\u2500".repeat(80));
|
|
959
|
+
for (const ws of wsList) {
|
|
960
|
+
const lastBackup = ws.lastBackupAt ? new Date(ws.lastBackupAt).toLocaleString() : "Never";
|
|
961
|
+
const current = ws.id === cfg.workspaceId ? " \u2190 current" : "";
|
|
962
|
+
console.log(
|
|
963
|
+
`${ws.name.padEnd(20)} | ${ws.slug.padEnd(20)} | ${String(ws.snapshotCount).padEnd(9)} | ${lastBackup}${current}`
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
console.log(`
|
|
967
|
+
Total: ${wsList.length} workspace(s)`);
|
|
968
|
+
trackCliEvent(cfg.profileId, "cli_workspaces_listed", { count: wsList.length });
|
|
969
|
+
} catch (e) {
|
|
970
|
+
console.error(`\u2717 Failed to list workspaces: ${e.message}`);
|
|
971
|
+
process.exit(1);
|
|
972
|
+
}
|
|
973
|
+
});
|
|
974
|
+
workspaces.command("create <name>").description("Create a new workspace").option("--description <desc>", "Workspace description").action(async (name, opts) => {
|
|
975
|
+
const cfg = readConfig();
|
|
976
|
+
if (!cfg) {
|
|
977
|
+
console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
|
|
978
|
+
process.exit(1);
|
|
979
|
+
}
|
|
980
|
+
try {
|
|
981
|
+
const { workspace } = await api(
|
|
982
|
+
cfg.apiBaseUrl,
|
|
983
|
+
"/api/v1/workspaces/create",
|
|
984
|
+
"POST",
|
|
985
|
+
cfg.apiKey,
|
|
986
|
+
{
|
|
987
|
+
profileId: cfg.profileId,
|
|
988
|
+
name,
|
|
989
|
+
...opts.description ? { description: opts.description } : {}
|
|
990
|
+
}
|
|
991
|
+
);
|
|
992
|
+
console.log(`\u2713 Workspace created`);
|
|
993
|
+
console.log(` Name: ${workspace.name}`);
|
|
994
|
+
console.log(` Slug: ${workspace.slug}`);
|
|
995
|
+
console.log(`
|
|
996
|
+
Switch to it: clawon workspaces switch ${workspace.slug}`);
|
|
997
|
+
trackCliEvent(cfg.profileId, "workspace_created", { name, slug: workspace.slug });
|
|
998
|
+
} catch (e) {
|
|
999
|
+
console.error(`\u2717 Failed to create workspace: ${e.message}`);
|
|
1000
|
+
process.exit(1);
|
|
1001
|
+
}
|
|
1002
|
+
});
|
|
1003
|
+
workspaces.command("switch <slug>").description("Switch to a different workspace").action(async (slug) => {
|
|
1004
|
+
const cfg = readConfig();
|
|
1005
|
+
if (!cfg) {
|
|
1006
|
+
console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
|
|
1007
|
+
process.exit(1);
|
|
1008
|
+
}
|
|
1009
|
+
try {
|
|
1010
|
+
const { workspaces: wsList } = await api(
|
|
1011
|
+
cfg.apiBaseUrl,
|
|
1012
|
+
`/api/v1/workspaces/list?profileId=${cfg.profileId}`,
|
|
1013
|
+
"GET",
|
|
1014
|
+
cfg.apiKey
|
|
1015
|
+
);
|
|
1016
|
+
const target = (wsList || []).find((w) => w.slug === slug);
|
|
1017
|
+
if (!target) {
|
|
1018
|
+
console.error(`\u2717 Workspace "${slug}" not found.`);
|
|
1019
|
+
console.error(" Available workspaces:");
|
|
1020
|
+
for (const ws of wsList || []) {
|
|
1021
|
+
console.error(` \u2022 ${ws.slug}`);
|
|
1022
|
+
}
|
|
1023
|
+
process.exit(1);
|
|
1024
|
+
}
|
|
1025
|
+
const previousSlug = cfg.workspaceSlug;
|
|
1026
|
+
updateConfig({ workspaceId: target.id, workspaceSlug: target.slug });
|
|
1027
|
+
console.log(`\u2713 Switched to workspace: ${target.name} (${target.slug})`);
|
|
1028
|
+
trackCliEvent(cfg.profileId, "workspace_switched", {
|
|
1029
|
+
from_slug: previousSlug,
|
|
1030
|
+
to_slug: target.slug
|
|
1031
|
+
});
|
|
1032
|
+
} catch (e) {
|
|
1033
|
+
console.error(`\u2717 Failed to switch workspace: ${e.message}`);
|
|
1034
|
+
process.exit(1);
|
|
1035
|
+
}
|
|
1036
|
+
});
|
|
1037
|
+
workspaces.command("info").description("Show current workspace info").action(async () => {
|
|
1038
|
+
const cfg = readConfig();
|
|
1039
|
+
if (!cfg) {
|
|
1040
|
+
console.error("\u2717 Not logged in. Run: clawon login --api-key <key>");
|
|
1041
|
+
process.exit(1);
|
|
1042
|
+
}
|
|
1043
|
+
if (!cfg.workspaceId) {
|
|
1044
|
+
console.log("No workspace selected. Run: clawon workspaces switch <slug>");
|
|
1045
|
+
return;
|
|
1046
|
+
}
|
|
1047
|
+
try {
|
|
1048
|
+
const { workspaces: wsList } = await api(
|
|
1049
|
+
cfg.apiBaseUrl,
|
|
1050
|
+
`/api/v1/workspaces/list?profileId=${cfg.profileId}`,
|
|
1051
|
+
"GET",
|
|
1052
|
+
cfg.apiKey
|
|
1053
|
+
);
|
|
1054
|
+
const current = (wsList || []).find((w) => w.id === cfg.workspaceId);
|
|
1055
|
+
if (!current) {
|
|
1056
|
+
console.log("Current workspace not found on server. It may have been deleted.");
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
console.log("Current Workspace\n");
|
|
1060
|
+
console.log(` Name: ${current.name}`);
|
|
1061
|
+
console.log(` Slug: ${current.slug}`);
|
|
1062
|
+
console.log(` Snapshots: ${current.snapshotCount}`);
|
|
1063
|
+
if (current.lastBackupAt) {
|
|
1064
|
+
console.log(` Last backup: ${new Date(current.lastBackupAt).toLocaleString()}`);
|
|
1065
|
+
}
|
|
1066
|
+
if (current.description) {
|
|
1067
|
+
console.log(` Description: ${current.description}`);
|
|
1068
|
+
}
|
|
1069
|
+
} catch (e) {
|
|
1070
|
+
console.error(`\u2717 Failed to get workspace info: ${e.message}`);
|
|
1071
|
+
process.exit(1);
|
|
1072
|
+
}
|
|
1073
|
+
});
|
|
919
1074
|
program.command("status").description("Show current status").action(async () => {
|
|
920
1075
|
const cfg = readConfig();
|
|
921
1076
|
console.log("Clawon Status\n");
|
|
922
1077
|
if (cfg) {
|
|
923
1078
|
console.log(`\u2713 Logged in`);
|
|
924
1079
|
console.log(` Profile ID: ${cfg.profileId}`);
|
|
1080
|
+
if (cfg.workspaceSlug) {
|
|
1081
|
+
console.log(` Workspace: ${cfg.workspaceSlug}`);
|
|
1082
|
+
}
|
|
925
1083
|
console.log(` API: ${cfg.apiBaseUrl}`);
|
|
926
1084
|
} else {
|
|
927
1085
|
console.log(`\u2717 Not logged in`);
|