shiva-code 0.5.4 → 0.6.0

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/dist/index.js CHANGED
@@ -1,7 +1,17 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ addProjectToPackage,
4
+ createPackage,
5
+ deletePackage,
6
+ getAllPackages,
7
+ getPackage,
8
+ getPackageLaunchConfig,
9
+ getPackageStats,
10
+ removeProjectFromPackage
11
+ } from "./chunk-LBTCSQAX.js";
2
12
  import {
3
13
  api
4
- } from "./chunk-XVFDKDRZ.js";
14
+ } from "./chunk-2DKDGG4A.js";
5
15
  import {
6
16
  CONFIG_PATH,
7
17
  clearAuth,
@@ -21,6 +31,33 @@ import {
21
31
  setConfig,
22
32
  setDefaultTerminal
23
33
  } from "./chunk-OP4HYQZZ.js";
34
+ import {
35
+ colors,
36
+ log
37
+ } from "./chunk-Z6NXFC4Q.js";
38
+ import {
39
+ encodeProjectPath,
40
+ findProject,
41
+ findProjectForCurrentDir,
42
+ findProjectFromArray,
43
+ findSessionByBranch,
44
+ formatDate,
45
+ formatRelativeTime,
46
+ getAllClaudeProjects,
47
+ getClaudeProjectsPath,
48
+ getProjectName,
49
+ getRecoveredContext,
50
+ getSessionStats,
51
+ invalidateSessionsCache,
52
+ isSessionActive,
53
+ isSessionCorrupted,
54
+ isSessionCorruptedQuick,
55
+ isValidProjectPath,
56
+ isValidSessionId,
57
+ maskSecret,
58
+ sanitizeForLog,
59
+ saveRecoveredContext
60
+ } from "./chunk-H5OFO4VS.js";
24
61
  import {
25
62
  SECURITY_PRESETS,
26
63
  addDockerMount,
@@ -62,168 +99,26 @@ import {
62
99
  isGhInstalled,
63
100
  isGitRepo
64
101
  } from "./chunk-IVFCZLBX.js";
65
- import {
66
- addProjectToPackage,
67
- createPackage,
68
- deletePackage,
69
- getAllPackages,
70
- getPackage,
71
- getPackageLaunchConfig,
72
- getPackageStats,
73
- removeProjectFromPackage
74
- } from "./chunk-LBTCSQAX.js";
75
- import {
76
- encodeProjectPath,
77
- findProject,
78
- findProjectForCurrentDir,
79
- findProjectFromArray,
80
- findSessionByBranch,
81
- formatDate,
82
- formatRelativeTime,
83
- getAllClaudeProjects,
84
- getClaudeProjectsPath,
85
- getProjectName,
86
- getRecoveredContext,
87
- getSessionStats,
88
- invalidateSessionsCache,
89
- isSessionActive,
90
- isSessionCorrupted,
91
- isSessionCorruptedQuick,
92
- isValidProjectPath,
93
- isValidSessionId,
94
- maskSecret,
95
- sanitizeForLog,
96
- saveRecoveredContext
97
- } from "./chunk-H5OFO4VS.js";
98
102
  import {
99
103
  cache
100
104
  } from "./chunk-HIQO2DBA.js";
105
+ import {
106
+ copyToClipboard,
107
+ getClipboardInstallInstructions,
108
+ isClipboardAvailable
109
+ } from "./chunk-WWGAGUNY.js";
101
110
  import {
102
111
  __require
103
112
  } from "./chunk-3RG5ZIWI.js";
104
113
 
105
114
  // src/index.ts
106
- import { Command as Command36 } from "commander";
115
+ import { Command as Command38 } from "commander";
107
116
  import * as readline from "readline";
108
117
 
109
118
  // src/commands/auth/login.ts
110
119
  import { Command } from "commander";
111
120
  import inquirer2 from "inquirer";
112
121
 
113
- // src/utils/logger.ts
114
- import chalk from "chalk";
115
- var log = {
116
- // Success messages
117
- success: (message) => console.log(chalk.green("\u2713"), message),
118
- // Error messages
119
- error: (message) => console.log(chalk.red("\u2717"), message),
120
- // Warning messages
121
- warn: (message) => console.log(chalk.yellow("\u26A0"), message),
122
- // Info messages
123
- info: (message) => console.log(chalk.blue("\u2139"), message),
124
- // Plain message
125
- plain: (message) => console.log(message),
126
- // Dimmed text
127
- dim: (message) => console.log(chalk.dim(message)),
128
- // Bold text
129
- bold: (message) => console.log(chalk.bold(message)),
130
- // Newline
131
- newline: () => console.log(),
132
- // Header
133
- header: (title) => {
134
- console.log();
135
- console.log(chalk.bold(title));
136
- console.log(chalk.dim("\u2500".repeat(title.length)));
137
- },
138
- // Key-value pair
139
- keyValue: (key, value, indent = 0) => {
140
- const spaces = " ".repeat(indent);
141
- console.log(`${spaces}${chalk.dim(key + ":")} ${value}`);
142
- },
143
- // List item
144
- listItem: (text, status) => {
145
- let icon = "\u2022";
146
- if (status === "synced") icon = chalk.green("\u2713");
147
- if (status === "pending") icon = chalk.yellow("\u25CB");
148
- if (status === "error") icon = chalk.red("\u2717");
149
- console.log(` ${icon} ${text}`);
150
- },
151
- // Tree structure
152
- tree: {
153
- item: (text, isLast = false) => {
154
- const prefix = isLast ? "\u2514\u2500" : "\u251C\u2500";
155
- console.log(chalk.dim(prefix), text);
156
- }
157
- },
158
- // Branded header
159
- brand: () => {
160
- console.log();
161
- console.log(chalk.hex("#FF6B2C").bold("SHIVA Code"));
162
- console.log(chalk.dim("Makes Claude Code Persistent"));
163
- console.log();
164
- },
165
- // Error with suggestion (for ShivaError)
166
- errorWithSuggestion: (error) => {
167
- console.log(chalk.red("\u2717"), error.message);
168
- if (error.suggestion) {
169
- console.log(chalk.dim(` \u2192 ${error.suggestion}`));
170
- }
171
- },
172
- // Progress bar
173
- progress: (current, total, label) => {
174
- const percentage = Math.round(current / total * 100);
175
- const barWidth = 20;
176
- const filled = Math.round(current / total * barWidth);
177
- const empty = barWidth - filled;
178
- const bar = chalk.green("\u2588".repeat(filled)) + chalk.dim("\u2591".repeat(empty));
179
- const counts = chalk.dim(`${current}/${total}`);
180
- const labelStr = label ? ` ${label}` : "";
181
- process.stdout.write(`\r[${bar}] ${counts}${labelStr}`);
182
- if (current >= total) {
183
- console.log();
184
- }
185
- },
186
- // Status line (inline update)
187
- status: (message) => {
188
- process.stdout.write(`\r${chalk.dim("\u2192")} ${message}`.padEnd(60));
189
- },
190
- // Clear the current line
191
- clearLine: () => {
192
- process.stdout.write("\r" + " ".repeat(80) + "\r");
193
- },
194
- // Box with title
195
- box: (title, content) => {
196
- const maxLen = Math.max(title.length, ...content.map((l) => l.length));
197
- const border = "\u2500".repeat(maxLen + 2);
198
- console.log(chalk.dim(`\u250C${border}\u2510`));
199
- console.log(chalk.dim("\u2502 ") + chalk.bold(title.padEnd(maxLen)) + chalk.dim(" \u2502"));
200
- console.log(chalk.dim(`\u251C${border}\u2524`));
201
- for (const line of content) {
202
- console.log(chalk.dim("\u2502 ") + line.padEnd(maxLen) + chalk.dim(" \u2502"));
203
- }
204
- console.log(chalk.dim(`\u2514${border}\u2518`));
205
- },
206
- // Table row
207
- tableRow: (columns, widths) => {
208
- const padded = columns.map((col, i) => col.padEnd(widths[i] || col.length));
209
- console.log(" " + padded.join(" "));
210
- },
211
- // Separator line
212
- separator: (char = "\u2500", length = 40) => {
213
- console.log(chalk.dim(char.repeat(length)));
214
- }
215
- };
216
- var colors = {
217
- orange: chalk.hex("#FF6B2C"),
218
- cyan: chalk.hex("#00D4FF"),
219
- green: chalk.green,
220
- red: chalk.red,
221
- yellow: chalk.yellow,
222
- blue: chalk.blue,
223
- dim: chalk.dim,
224
- bold: chalk.bold
225
- };
226
-
227
122
  // src/services/auth/auth.ts
228
123
  import inquirer from "inquirer";
229
124
  import open from "open";
@@ -6775,7 +6670,7 @@ async function checkProjectExists(path15) {
6775
6670
  }
6776
6671
  }
6777
6672
  sessionsCommand.command("push").description("Sessions in Cloud sichern").option("-p, --project <pfad>", "Nur Sessions eines Projekts").action(async (options) => {
6778
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
6673
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6779
6674
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6780
6675
  const { getProjectConfig: getProjectConfig2 } = await import("./config-D6M6LI6U.js");
6781
6676
  if (!isAuthenticated2()) {
@@ -6835,7 +6730,7 @@ sessionsCommand.command("push").description("Sessions in Cloud sichern").option(
6835
6730
  }
6836
6731
  });
6837
6732
  sessionsCommand.command("pull").description("Sessions aus Cloud laden").option("--json", "JSON Output").action(async (options) => {
6838
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
6733
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6839
6734
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6840
6735
  if (!isAuthenticated2()) {
6841
6736
  log.error("Nicht angemeldet");
@@ -6882,7 +6777,7 @@ sessionsCommand.command("pull").description("Sessions aus Cloud laden").option("
6882
6777
  }
6883
6778
  });
6884
6779
  sessionsCommand.command("sync").description("Sessions mit Cloud synchronisieren").option("-p, --project <pfad>", "Nur Sessions eines Projekts").action(async (options) => {
6885
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
6780
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6886
6781
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6887
6782
  const { getProjectConfig: getProjectConfig2 } = await import("./config-D6M6LI6U.js");
6888
6783
  if (!isAuthenticated2()) {
@@ -6935,7 +6830,7 @@ sessionsCommand.command("sync").description("Sessions mit Cloud synchronisieren"
6935
6830
  log.dim("Sessions werden automatisch mit lokalen Claude Sessions verkn\xFCpft");
6936
6831
  });
6937
6832
  sessionsCommand.command("delete <sessionId>").description("Session aus Cloud l\xF6schen").action(async (sessionId) => {
6938
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
6833
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6939
6834
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6940
6835
  if (!isAuthenticated2()) {
6941
6836
  log.error("Nicht angemeldet");
@@ -6953,6 +6848,152 @@ sessionsCommand.command("delete <sessionId>").description("Session aus Cloud l\x
6953
6848
  log.error(error instanceof Error ? error.message : "Fehler beim L\xF6schen");
6954
6849
  }
6955
6850
  });
6851
+ sessionsCommand.command("active").description("Aktive Cloud-Sessions anzeigen").option("--json", "JSON Output").action(async (options) => {
6852
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6853
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6854
+ if (!isAuthenticated2()) {
6855
+ log.error("Nicht angemeldet");
6856
+ log.info("Anmelden mit: shiva login");
6857
+ return;
6858
+ }
6859
+ const spinner = ora9("Lade aktive Sessions...").start();
6860
+ try {
6861
+ const sessions = await api2.getActiveSessions();
6862
+ spinner.stop();
6863
+ if (options.json) {
6864
+ console.log(JSON.stringify(sessions, null, 2));
6865
+ return;
6866
+ }
6867
+ log.newline();
6868
+ console.log(colors.orange.bold("Active Cloud Sessions"));
6869
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
6870
+ log.newline();
6871
+ if (sessions.length === 0) {
6872
+ log.dim("Keine aktiven Cloud-Sessions");
6873
+ return;
6874
+ }
6875
+ for (const session of sessions) {
6876
+ console.log(` ${colors.green("\u25CF")} ${colors.bold(session.sessionId)}`);
6877
+ console.log(` ${colors.dim("Project ID:")} ${session.projectId}`);
6878
+ console.log(` ${colors.dim("Started:")} ${session.startedAt}`);
6879
+ console.log(` ${colors.dim("Last Activity:")} ${session.lastActivity}`);
6880
+ console.log(` ${colors.dim("Messages:")} ${session.messageCount}`);
6881
+ log.newline();
6882
+ }
6883
+ } catch (error) {
6884
+ spinner.fail("Fehler beim Laden");
6885
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
6886
+ }
6887
+ });
6888
+ sessionsCommand.command("stats").description("Cloud-Session-Statistiken anzeigen").option("--json", "JSON Output").action(async (options) => {
6889
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6890
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6891
+ if (!isAuthenticated2()) {
6892
+ log.error("Nicht angemeldet");
6893
+ log.info("Anmelden mit: shiva login");
6894
+ return;
6895
+ }
6896
+ const spinner = ora9("Lade Session-Statistiken...").start();
6897
+ try {
6898
+ const stats = await api2.getSessionStats();
6899
+ spinner.stop();
6900
+ if (options.json) {
6901
+ console.log(JSON.stringify(stats, null, 2));
6902
+ return;
6903
+ }
6904
+ log.newline();
6905
+ console.log(colors.orange.bold("Session Statistics"));
6906
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
6907
+ log.newline();
6908
+ log.keyValue("Total Sessions", String(stats.totalSessions));
6909
+ log.keyValue("Active Sessions", String(stats.activeSessions));
6910
+ log.keyValue("Total Messages", String(stats.totalMessages));
6911
+ log.keyValue("Avg Session Length", `${stats.averageSessionLength} min`);
6912
+ log.newline();
6913
+ log.keyValue("Sessions (Last 7 Days)", String(stats.sessionsLast7Days));
6914
+ log.keyValue("Sessions (Last 30 Days)", String(stats.sessionsLast30Days));
6915
+ } catch (error) {
6916
+ spinner.fail("Fehler beim Laden");
6917
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
6918
+ }
6919
+ });
6920
+ sessionsCommand.command("resume <sessionId>").description("Cloud-Session fortsetzen").action(async (sessionId) => {
6921
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6922
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6923
+ if (!isAuthenticated2()) {
6924
+ log.error("Nicht angemeldet");
6925
+ log.info("Anmelden mit: shiva login");
6926
+ return;
6927
+ }
6928
+ const spinner = ora9("Lade Session...").start();
6929
+ try {
6930
+ const result = await api2.resumeSession(sessionId);
6931
+ if (result.success) {
6932
+ spinner.succeed("Session geladen");
6933
+ log.newline();
6934
+ log.info("Session kann jetzt fortgesetzt werden");
6935
+ log.plain(` claude --session ${sessionId}`);
6936
+ } else {
6937
+ spinner.fail(result.message || "Fehler beim Laden");
6938
+ }
6939
+ } catch (error) {
6940
+ spinner.fail("Fehler beim Laden");
6941
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
6942
+ }
6943
+ });
6944
+ sessionsCommand.command("export <sessionId>").description("Cloud-Session exportieren").option("-o, --output <file>", "Ausgabedatei").action(async (sessionId, options) => {
6945
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6946
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6947
+ const { writeFileSync: writeFileSync11 } = await import("fs");
6948
+ if (!isAuthenticated2()) {
6949
+ log.error("Nicht angemeldet");
6950
+ log.info("Anmelden mit: shiva login");
6951
+ return;
6952
+ }
6953
+ const spinner = ora9("Exportiere Session...").start();
6954
+ try {
6955
+ const exportData = await api2.exportSession(sessionId);
6956
+ spinner.stop();
6957
+ if (options.output) {
6958
+ writeFileSync11(options.output, JSON.stringify(exportData, null, 2));
6959
+ log.success(`Session exportiert: ${options.output}`);
6960
+ } else {
6961
+ console.log(JSON.stringify(exportData, null, 2));
6962
+ }
6963
+ } catch (error) {
6964
+ spinner.fail("Fehler beim Exportieren");
6965
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
6966
+ }
6967
+ });
6968
+ sessionsCommand.command("update <sessionId>").description("Cloud-Session aktualisieren").option("--summary <text>", "Session-Zusammenfassung").option("--branch <name>", "Git Branch").action(async (sessionId, options) => {
6969
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6970
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6971
+ if (!isAuthenticated2()) {
6972
+ log.error("Nicht angemeldet");
6973
+ log.info("Anmelden mit: shiva login");
6974
+ return;
6975
+ }
6976
+ if (!options.summary && !options.branch) {
6977
+ log.error("Keine \xC4nderungen angegeben");
6978
+ log.info("Verf\xFCgbare Optionen: --summary, --branch");
6979
+ return;
6980
+ }
6981
+ const spinner = ora9("Aktualisiere Session...").start();
6982
+ try {
6983
+ const result = await api2.updateSession(sessionId, {
6984
+ summary: options.summary,
6985
+ gitBranch: options.branch
6986
+ });
6987
+ if (result.success) {
6988
+ spinner.succeed("Session aktualisiert");
6989
+ } else {
6990
+ spinner.fail(result.message || "Fehler beim Aktualisieren");
6991
+ }
6992
+ } catch (error) {
6993
+ spinner.fail("Fehler beim Aktualisieren");
6994
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
6995
+ }
6996
+ });
6956
6997
 
6957
6998
  // src/commands/session/session.ts
6958
6999
  import { Command as Command14 } from "commander";
@@ -10389,67 +10430,6 @@ import inquirer8 from "inquirer";
10389
10430
  import ora13 from "ora";
10390
10431
  import * as fs6 from "fs";
10391
10432
  import * as path6 from "path";
10392
-
10393
- // src/utils/clipboard.ts
10394
- import { execSync as execSync2, spawnSync as spawnSync6 } from "child_process";
10395
- var CLIPBOARD_COMMANDS = [
10396
- // Wayland (modern Linux)
10397
- { command: "wl-copy", args: [], check: "wl-copy" },
10398
- // X11 - xclip
10399
- { command: "xclip", args: ["-selection", "clipboard"], check: "xclip" },
10400
- // X11 - xsel
10401
- { command: "xsel", args: ["--clipboard", "--input"], check: "xsel" },
10402
- // macOS
10403
- { command: "pbcopy", args: [], check: "pbcopy" }
10404
- ];
10405
- function commandExists2(command) {
10406
- try {
10407
- execSync2(`which ${command}`, { stdio: "ignore" });
10408
- return true;
10409
- } catch {
10410
- return false;
10411
- }
10412
- }
10413
- function findClipboardCommand() {
10414
- for (const cmd of CLIPBOARD_COMMANDS) {
10415
- if (commandExists2(cmd.check)) {
10416
- return cmd;
10417
- }
10418
- }
10419
- return null;
10420
- }
10421
- function copyToClipboard(text) {
10422
- const clipboardCmd = findClipboardCommand();
10423
- if (!clipboardCmd) {
10424
- return false;
10425
- }
10426
- try {
10427
- const result = spawnSync6(clipboardCmd.command, clipboardCmd.args, {
10428
- input: text,
10429
- stdio: ["pipe", "ignore", "ignore"]
10430
- });
10431
- return result.status === 0;
10432
- } catch {
10433
- return false;
10434
- }
10435
- }
10436
- function isClipboardAvailable() {
10437
- return findClipboardCommand() !== null;
10438
- }
10439
- function getClipboardInstallInstructions() {
10440
- const isWayland = process.env.WAYLAND_DISPLAY || process.env.XDG_SESSION_TYPE === "wayland";
10441
- const isX11 = process.env.DISPLAY && !isWayland;
10442
- if (isWayland) {
10443
- return "F\xFCr Wayland: sudo apt install wl-clipboard";
10444
- } else if (isX11) {
10445
- return "F\xFCr X11: sudo apt install xclip";
10446
- } else if (process.platform === "darwin") {
10447
- return "pbcopy sollte bereits verf\xFCgbar sein";
10448
- }
10449
- return "sudo apt install wl-clipboard (Wayland) oder xclip (X11)";
10450
- }
10451
-
10452
- // src/commands/security/secrets.ts
10453
10433
  var SECURE_FILE_MODE = 384;
10454
10434
  var secretsCommand = new Command20("secrets").description("API Keys und Secrets verwalten (Cloud Vault)").action(async () => {
10455
10435
  await listSecrets();
@@ -11802,7 +11782,8 @@ function getColorFunction(color) {
11802
11782
  case "yellow":
11803
11783
  return colors.yellow;
11804
11784
  case "magenta":
11805
- return colors.magenta;
11785
+ return colors.cyan;
11786
+ // magenta not available, use cyan
11806
11787
  case "cyan":
11807
11788
  return colors.cyan;
11808
11789
  default:
@@ -11830,6 +11811,40 @@ async function resolveSessionId(input) {
11830
11811
  }
11831
11812
  return null;
11832
11813
  }
11814
+ tagsCommand.command("cloud").description("Memory-Tags aus Cloud laden").option("--json", "JSON Output").action(async (options) => {
11815
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
11816
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
11817
+ if (!isAuthenticated2()) {
11818
+ log.error("Nicht angemeldet");
11819
+ log.info("Anmelden mit: shiva login");
11820
+ return;
11821
+ }
11822
+ const ora24 = (await import("ora")).default;
11823
+ const spinner = ora24("Lade Memory-Tags aus Cloud...").start();
11824
+ try {
11825
+ const cloudTags = await api2.getMemoryTags();
11826
+ spinner.stop();
11827
+ if (options.json) {
11828
+ console.log(JSON.stringify(cloudTags, null, 2));
11829
+ return;
11830
+ }
11831
+ log.newline();
11832
+ console.log(colors.orange.bold("Memory Tags (Cloud)"));
11833
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11834
+ log.newline();
11835
+ if (cloudTags.length === 0) {
11836
+ log.dim("Keine Memory-Tags in Cloud");
11837
+ return;
11838
+ }
11839
+ for (const { tag, count } of cloudTags) {
11840
+ console.log(` ${colors.cyan(`[${tag}]`)} ${colors.dim(`(${count} Memories)`)}`);
11841
+ }
11842
+ log.newline();
11843
+ } catch (error) {
11844
+ spinner.fail("Fehler beim Laden");
11845
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
11846
+ }
11847
+ });
11833
11848
 
11834
11849
  // src/commands/memory/export.ts
11835
11850
  import { Command as Command25 } from "commander";
@@ -11841,7 +11856,7 @@ import inquirer11 from "inquirer";
11841
11856
  // src/services/session/export.ts
11842
11857
  import * as fs9 from "fs";
11843
11858
  import * as path10 from "path";
11844
- import { execSync as execSync3 } from "child_process";
11859
+ import { execSync as execSync2 } from "child_process";
11845
11860
  async function exportSession(sessionId, options = {}) {
11846
11861
  const projects = await getAllClaudeProjects();
11847
11862
  for (const project of projects) {
@@ -11953,7 +11968,7 @@ function createBackupArchive(outputPath, projectPaths) {
11953
11968
  return false;
11954
11969
  }
11955
11970
  const tarArgs = includePaths.join(" ");
11956
- execSync3(`tar -czf "${outputPath}" -C "${claudeDir}" ${tarArgs}`, {
11971
+ execSync2(`tar -czf "${outputPath}" -C "${claudeDir}" ${tarArgs}`, {
11957
11972
  stdio: "ignore"
11958
11973
  });
11959
11974
  return true;
@@ -12061,7 +12076,7 @@ function restoreFromArchive(archivePath, targetDir) {
12061
12076
  if (!fs9.existsSync(extractTo)) {
12062
12077
  fs9.mkdirSync(extractTo, { recursive: true });
12063
12078
  }
12064
- execSync3(`tar -xzf "${archivePath}" -C "${extractTo}"`, {
12079
+ execSync2(`tar -xzf "${archivePath}" -C "${extractTo}"`, {
12065
12080
  stdio: "ignore"
12066
12081
  });
12067
12082
  return true;
@@ -12340,20 +12355,20 @@ var rememberCommand = new Command26("remember").description("Memory in der Cloud
12340
12355
 
12341
12356
  // src/commands/system/doctor.ts
12342
12357
  import { Command as Command27 } from "commander";
12343
- import { execSync as execSync4 } from "child_process";
12358
+ import { execSync as execSync3 } from "child_process";
12344
12359
  import * as fs11 from "fs";
12345
12360
  import * as path12 from "path";
12346
12361
  import * as os5 from "os";
12347
12362
  function tryExec(command) {
12348
12363
  try {
12349
- return execSync4(command, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
12364
+ return execSync3(command, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
12350
12365
  } catch {
12351
12366
  return null;
12352
12367
  }
12353
12368
  }
12354
- function commandExists3(cmd) {
12369
+ function commandExists2(cmd) {
12355
12370
  try {
12356
- execSync4(`which ${cmd}`, { stdio: ["pipe", "pipe", "pipe"] });
12371
+ execSync3(`which ${cmd}`, { stdio: ["pipe", "pipe", "pipe"] });
12357
12372
  return true;
12358
12373
  } catch {
12359
12374
  return false;
@@ -12366,7 +12381,7 @@ function getVersion(cmd, versionFlag = "--version") {
12366
12381
  return match ? match[0] : output.split("\n")[0];
12367
12382
  }
12368
12383
  function checkClaude() {
12369
- const exists = commandExists3("claude");
12384
+ const exists = commandExists2("claude");
12370
12385
  if (!exists) {
12371
12386
  return {
12372
12387
  name: "Claude CLI",
@@ -12383,7 +12398,7 @@ function checkClaude() {
12383
12398
  };
12384
12399
  }
12385
12400
  function checkGitHub() {
12386
- const exists = commandExists3("gh");
12401
+ const exists = commandExists2("gh");
12387
12402
  if (!exists) {
12388
12403
  return {
12389
12404
  name: "GitHub CLI (gh)",
@@ -12404,7 +12419,7 @@ function checkGitHub() {
12404
12419
  };
12405
12420
  }
12406
12421
  function checkDocker() {
12407
- const dockerExists = commandExists3("docker");
12422
+ const dockerExists = commandExists2("docker");
12408
12423
  if (dockerExists) {
12409
12424
  const version = getVersion("docker");
12410
12425
  const isRunning = tryExec("docker info 2>/dev/null") !== null;
@@ -12416,7 +12431,7 @@ function checkDocker() {
12416
12431
  hint: isRunning ? void 0 : "Starte Docker Desktop oder: sudo systemctl start docker"
12417
12432
  };
12418
12433
  }
12419
- const podmanExists = commandExists3("podman");
12434
+ const podmanExists = commandExists2("podman");
12420
12435
  if (podmanExists) {
12421
12436
  const version = getVersion("podman");
12422
12437
  return {
@@ -12433,7 +12448,7 @@ function checkDocker() {
12433
12448
  };
12434
12449
  }
12435
12450
  function checkGit() {
12436
- const exists = commandExists3("git");
12451
+ const exists = commandExists2("git");
12437
12452
  if (!exists) {
12438
12453
  return {
12439
12454
  name: "Git",
@@ -12461,7 +12476,7 @@ function checkGit() {
12461
12476
  };
12462
12477
  }
12463
12478
  function checkNode() {
12464
- const exists = commandExists3("node");
12479
+ const exists = commandExists2("node");
12465
12480
  if (!exists) {
12466
12481
  return {
12467
12482
  name: "Node.js",
@@ -12488,7 +12503,7 @@ function checkNode() {
12488
12503
  };
12489
12504
  }
12490
12505
  function checkNpm() {
12491
- const exists = commandExists3("npm");
12506
+ const exists = commandExists2("npm");
12492
12507
  if (!exists) {
12493
12508
  return {
12494
12509
  name: "npm",
@@ -12556,7 +12571,7 @@ function checkClaudeProjects() {
12556
12571
  }
12557
12572
  }
12558
12573
  function checkTmux() {
12559
- const exists = commandExists3("tmux");
12574
+ const exists = commandExists2("tmux");
12560
12575
  if (!exists) {
12561
12576
  return {
12562
12577
  name: "tmux",
@@ -12667,7 +12682,7 @@ var doctorCommand = new Command27("doctor").description("System-Check f\xFCr SHI
12667
12682
 
12668
12683
  // src/commands/system/upgrade.ts
12669
12684
  import { Command as Command28 } from "commander";
12670
- import { execSync as execSync5, spawn as spawn6 } from "child_process";
12685
+ import { execSync as execSync4, spawn as spawn6 } from "child_process";
12671
12686
  import * as fs12 from "fs";
12672
12687
  import * as path13 from "path";
12673
12688
  import { fileURLToPath } from "url";
@@ -12693,7 +12708,7 @@ async function getLatestVersion() {
12693
12708
  return data["dist-tags"]?.latest || null;
12694
12709
  } catch {
12695
12710
  try {
12696
- const output = execSync5(`npm view ${PACKAGE_NAME} version 2>/dev/null`, {
12711
+ const output = execSync4(`npm view ${PACKAGE_NAME} version 2>/dev/null`, {
12697
12712
  encoding: "utf-8"
12698
12713
  }).trim();
12699
12714
  return output || null;
@@ -12724,17 +12739,17 @@ async function checkForUpdates() {
12724
12739
  }
12725
12740
  function detectPackageManager2() {
12726
12741
  try {
12727
- const npmGlobal = execSync5("npm list -g --depth=0 2>/dev/null", { encoding: "utf-8" });
12742
+ const npmGlobal = execSync4("npm list -g --depth=0 2>/dev/null", { encoding: "utf-8" });
12728
12743
  if (npmGlobal.includes(PACKAGE_NAME)) return "npm";
12729
12744
  } catch {
12730
12745
  }
12731
12746
  try {
12732
- const yarnGlobal = execSync5("yarn global list 2>/dev/null", { encoding: "utf-8" });
12747
+ const yarnGlobal = execSync4("yarn global list 2>/dev/null", { encoding: "utf-8" });
12733
12748
  if (yarnGlobal.includes(PACKAGE_NAME)) return "yarn";
12734
12749
  } catch {
12735
12750
  }
12736
12751
  try {
12737
- const pnpmGlobal = execSync5("pnpm list -g 2>/dev/null", { encoding: "utf-8" });
12752
+ const pnpmGlobal = execSync4("pnpm list -g 2>/dev/null", { encoding: "utf-8" });
12738
12753
  if (pnpmGlobal.includes(PACKAGE_NAME)) return "pnpm";
12739
12754
  } catch {
12740
12755
  }
@@ -13499,32 +13514,511 @@ function formatNumber(n) {
13499
13514
  }
13500
13515
  return String(n);
13501
13516
  }
13502
-
13503
- // src/commands/advanced/docker.ts
13504
- import { Command as Command32 } from "commander";
13505
- import ora19 from "ora";
13506
- var dockerCommand = new Command32("docker").description("Docker-Integration verwalten");
13507
- dockerCommand.command("status").description("Docker-Verf\xFCgbarkeit pr\xFCfen").action(() => {
13508
- log.brand();
13509
- log.header("Docker Status");
13510
- log.newline();
13511
- const info = dockerService.getDockerInfo();
13512
- const settings = settingsSync.getDockerSettings();
13513
- if (info.available) {
13514
- log.keyValue("Runtime", `${info.runtime === "podman" ? "Podman" : "Docker"} ${info.version}`);
13515
- log.keyValue("Socket", info.socket || colors.dim("default"));
13516
- log.keyValue("Status", colors.green("Verf\xFCgbar"));
13517
- } else {
13518
- log.keyValue("Runtime", colors.dim("nicht gefunden"));
13519
- log.keyValue("Status", colors.red("Nicht verf\xFCgbar"));
13520
- log.newline();
13521
- log.warn("Docker oder Podman ist nicht installiert");
13522
- log.dim("Installation:");
13523
- log.dim(" Docker: https://docs.docker.com/get-docker/");
13524
- log.dim(" Podman: https://podman.io/get-started");
13517
+ statsCommand.command("sessions").description("Session Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
13518
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
13519
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
13520
+ if (!isAuthenticated2()) {
13521
+ log.error("Nicht angemeldet");
13522
+ log.info("Anmelden mit: shiva login");
13525
13523
  return;
13526
13524
  }
13527
- log.newline();
13525
+ const spinner = ora18("Lade Session Analytics...").start();
13526
+ try {
13527
+ const analytics = await api2.getSessionAnalytics();
13528
+ spinner.stop();
13529
+ if (options.json) {
13530
+ console.log(JSON.stringify(analytics, null, 2));
13531
+ return;
13532
+ }
13533
+ log.newline();
13534
+ console.log(colors.orange.bold("Session Analytics"));
13535
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13536
+ log.newline();
13537
+ log.keyValue("Avg Session Length", `${analytics.averageSessionLength} min`);
13538
+ log.newline();
13539
+ console.log(colors.bold("Peak Hours:"));
13540
+ const sortedHours = analytics.peakHours.sort((a, b) => b.count - a.count).slice(0, 5);
13541
+ for (const { hour, count } of sortedHours) {
13542
+ console.log(` ${String(hour).padStart(2)}:00 - ${count} sessions`);
13543
+ }
13544
+ log.newline();
13545
+ console.log(colors.bold("Top Projects by Sessions:"));
13546
+ for (const proj of analytics.topProjects.slice(0, 5)) {
13547
+ console.log(` ${proj.projectName.padEnd(25)} ${proj.sessionCount} sessions`);
13548
+ }
13549
+ log.newline();
13550
+ if (analytics.dailySessions.length > 0) {
13551
+ console.log(colors.bold("Sessions (Last 7 Days):"));
13552
+ for (const { date, count } of analytics.dailySessions.slice(-7)) {
13553
+ const barLength = Math.min(20, count);
13554
+ const bar = colors.green("\u2588".repeat(barLength));
13555
+ console.log(` ${date.slice(5)} ${bar} ${count}`);
13556
+ }
13557
+ }
13558
+ } catch (error) {
13559
+ spinner.fail("Fehler beim Laden");
13560
+ const err = error;
13561
+ if (err.message?.includes("403") || err.message?.includes("forbidden")) {
13562
+ log.warn("Session Analytics ist ein Pro-Feature");
13563
+ log.info("Upgrade auf Pro: https://shiva.li/pricing");
13564
+ } else {
13565
+ log.error(err.message || "Unbekannter Fehler");
13566
+ }
13567
+ }
13568
+ });
13569
+ statsCommand.command("tokens").description("Token Usage Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
13570
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
13571
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
13572
+ if (!isAuthenticated2()) {
13573
+ log.error("Nicht angemeldet");
13574
+ log.info("Anmelden mit: shiva login");
13575
+ return;
13576
+ }
13577
+ const spinner = ora18("Lade Token Analytics...").start();
13578
+ try {
13579
+ const analytics = await api2.getTokenAnalytics();
13580
+ spinner.stop();
13581
+ if (options.json) {
13582
+ console.log(JSON.stringify(analytics, null, 2));
13583
+ return;
13584
+ }
13585
+ log.newline();
13586
+ console.log(colors.orange.bold("Token Usage Analytics"));
13587
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13588
+ log.newline();
13589
+ log.keyValue("Total Tokens", formatNumber(analytics.totalTokens));
13590
+ log.keyValue("This Month", formatNumber(analytics.tokensThisMonth));
13591
+ log.newline();
13592
+ console.log(colors.bold("Token Usage by Project:"));
13593
+ for (const proj of analytics.byProject.slice(0, 5)) {
13594
+ console.log(` ${proj.projectName.padEnd(25)} ${formatNumber(proj.tokens)}`);
13595
+ }
13596
+ log.newline();
13597
+ if (analytics.dailyUsage.length > 0) {
13598
+ console.log(colors.bold("Daily Usage (Last 7 Days):"));
13599
+ const maxTokens = Math.max(...analytics.dailyUsage.slice(-7).map((d) => d.tokens), 1);
13600
+ for (const { date, tokens } of analytics.dailyUsage.slice(-7)) {
13601
+ const barLength = Math.round(tokens / maxTokens * 20);
13602
+ const bar = colors.cyan("\u2588".repeat(barLength)) + colors.dim("\u2591".repeat(20 - barLength));
13603
+ console.log(` ${date.slice(5)} ${bar} ${formatNumber(tokens)}`);
13604
+ }
13605
+ }
13606
+ } catch (error) {
13607
+ spinner.fail("Fehler beim Laden");
13608
+ const err = error;
13609
+ if (err.message?.includes("403") || err.message?.includes("forbidden")) {
13610
+ log.warn("Token Analytics ist ein Pro-Feature");
13611
+ log.info("Upgrade auf Pro: https://shiva.li/pricing");
13612
+ } else {
13613
+ log.error(err.message || "Unbekannter Fehler");
13614
+ }
13615
+ }
13616
+ });
13617
+ statsCommand.command("tools").description("Tool Usage Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
13618
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
13619
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
13620
+ if (!isAuthenticated2()) {
13621
+ log.error("Nicht angemeldet");
13622
+ log.info("Anmelden mit: shiva login");
13623
+ return;
13624
+ }
13625
+ const spinner = ora18("Lade Tool Analytics...").start();
13626
+ try {
13627
+ const analytics = await api2.getToolAnalytics();
13628
+ spinner.stop();
13629
+ if (options.json) {
13630
+ console.log(JSON.stringify(analytics, null, 2));
13631
+ return;
13632
+ }
13633
+ log.newline();
13634
+ console.log(colors.orange.bold("Tool Usage Analytics"));
13635
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13636
+ log.newline();
13637
+ log.keyValue("Total Tool Calls", formatNumber(analytics.totalToolCalls));
13638
+ log.newline();
13639
+ console.log(colors.bold("Most Used Tools:"));
13640
+ for (const tool of analytics.mostUsedTools.slice(0, 10)) {
13641
+ const bar = colors.yellow("\u2588".repeat(Math.min(20, Math.round(tool.count / 10))));
13642
+ console.log(` ${tool.tool.padEnd(20)} ${bar} ${formatNumber(tool.count)}`);
13643
+ }
13644
+ log.newline();
13645
+ console.log(colors.bold("Tool Performance (Avg Duration):"));
13646
+ const sorted = analytics.byTool.sort((a, b) => b.avgDuration - a.avgDuration).slice(0, 5);
13647
+ for (const tool of sorted) {
13648
+ console.log(` ${tool.tool.padEnd(20)} ${tool.avgDuration.toFixed(0)}ms`);
13649
+ }
13650
+ } catch (error) {
13651
+ spinner.fail("Fehler beim Laden");
13652
+ const err = error;
13653
+ if (err.message?.includes("403") || err.message?.includes("forbidden")) {
13654
+ log.warn("Tool Analytics ist ein Pro-Feature");
13655
+ log.info("Upgrade auf Pro: https://shiva.li/pricing");
13656
+ } else {
13657
+ log.error(err.message || "Unbekannter Fehler");
13658
+ }
13659
+ }
13660
+ });
13661
+ statsCommand.command("export").description("Analytics-Daten exportieren (Pro Feature)").option("--start <date>", "Start-Datum (YYYY-MM-DD)").option("--end <date>", "End-Datum (YYYY-MM-DD)").option("--format <format>", "Format: json, csv", "json").option("-o, --output <file>", "Ausgabedatei").action(async (options) => {
13662
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
13663
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
13664
+ const { writeFileSync: writeFileSync11 } = await import("fs");
13665
+ if (!isAuthenticated2()) {
13666
+ log.error("Nicht angemeldet");
13667
+ log.info("Anmelden mit: shiva login");
13668
+ return;
13669
+ }
13670
+ const spinner = ora18("Exportiere Analytics...").start();
13671
+ try {
13672
+ const result = await api2.exportAnalytics({
13673
+ startDate: options.start,
13674
+ endDate: options.end,
13675
+ format: options.format
13676
+ });
13677
+ spinner.stop();
13678
+ if (options.output) {
13679
+ const content = options.format === "json" ? JSON.stringify(result.data, null, 2) : String(result.data);
13680
+ writeFileSync11(options.output, content);
13681
+ log.success(`Analytics exportiert: ${options.output}`);
13682
+ } else {
13683
+ console.log(JSON.stringify(result, null, 2));
13684
+ }
13685
+ } catch (error) {
13686
+ spinner.fail("Fehler beim Exportieren");
13687
+ const err = error;
13688
+ if (err.message?.includes("403") || err.message?.includes("forbidden")) {
13689
+ log.warn("Analytics Export ist ein Pro-Feature");
13690
+ log.info("Upgrade auf Pro: https://shiva.li/pricing");
13691
+ } else {
13692
+ log.error(err.message || "Unbekannter Fehler");
13693
+ }
13694
+ }
13695
+ });
13696
+ statsCommand.command("track").description("Analytics Event tracken").argument("<type>", "Event-Typ").argument("[data]", "Event-Daten als JSON").action(async (type2, data) => {
13697
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
13698
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
13699
+ if (!isAuthenticated2()) {
13700
+ log.error("Nicht angemeldet");
13701
+ log.info("Anmelden mit: shiva login");
13702
+ return;
13703
+ }
13704
+ try {
13705
+ const eventData = data ? JSON.parse(data) : {};
13706
+ const result = await api2.trackAnalyticsEvent({
13707
+ type: type2,
13708
+ data: eventData
13709
+ });
13710
+ if (result.success) {
13711
+ log.success("Event getrackt");
13712
+ } else {
13713
+ log.error("Event konnte nicht getrackt werden");
13714
+ }
13715
+ } catch (error) {
13716
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13717
+ }
13718
+ });
13719
+
13720
+ // src/commands/system/user.ts
13721
+ import { Command as Command32 } from "commander";
13722
+ import ora19 from "ora";
13723
+ var userCommand = new Command32("user").description("User Account Verwaltung");
13724
+ userCommand.command("profile").description("User-Profil anzeigen").option("--json", "JSON Output").action(async (options) => {
13725
+ if (!isAuthenticated()) {
13726
+ log.error("Nicht angemeldet");
13727
+ log.info("Anmelden mit: shiva login");
13728
+ return;
13729
+ }
13730
+ const spinner = ora19("Lade Profil...").start();
13731
+ try {
13732
+ const profile = await api.getUserProfile();
13733
+ spinner.stop();
13734
+ if (options.json) {
13735
+ console.log(JSON.stringify(profile, null, 2));
13736
+ return;
13737
+ }
13738
+ log.newline();
13739
+ console.log(colors.orange.bold("User Profile"));
13740
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13741
+ log.newline();
13742
+ log.keyValue("ID", String(profile.id));
13743
+ log.keyValue("Email", profile.email);
13744
+ if (profile.name) {
13745
+ log.keyValue("Name", profile.name);
13746
+ }
13747
+ const tierColor = profile.tier === "pro" ? colors.cyan : profile.tier === "team" ? colors.green : colors.dim;
13748
+ log.keyValue("Tier", tierColor(profile.tier.toUpperCase()));
13749
+ log.keyValue("Seit", new Date(profile.createdAt).toLocaleDateString("de-DE"));
13750
+ } catch (error) {
13751
+ spinner.fail("Fehler beim Laden");
13752
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13753
+ }
13754
+ });
13755
+ userCommand.command("update").description("User-Profil aktualisieren").option("--name <name>", "Name setzen").action(async (options) => {
13756
+ if (!isAuthenticated()) {
13757
+ log.error("Nicht angemeldet");
13758
+ log.info("Anmelden mit: shiva login");
13759
+ return;
13760
+ }
13761
+ if (!options.name) {
13762
+ log.error("Keine \xC4nderungen angegeben");
13763
+ log.info("Verf\xFCgbare Optionen:");
13764
+ log.plain(" --name <name> Name setzen");
13765
+ return;
13766
+ }
13767
+ const spinner = ora19("Aktualisiere Profil...").start();
13768
+ try {
13769
+ const result = await api.updateUserProfile({
13770
+ name: options.name
13771
+ });
13772
+ if (result.success) {
13773
+ spinner.succeed("Profil aktualisiert");
13774
+ } else {
13775
+ spinner.fail(result.message || "Fehler beim Aktualisieren");
13776
+ }
13777
+ } catch (error) {
13778
+ spinner.fail("Fehler beim Aktualisieren");
13779
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13780
+ }
13781
+ });
13782
+ userCommand.command("usage").description("Resource-Nutzung und Limits anzeigen").option("--json", "JSON Output").action(async (options) => {
13783
+ if (!isAuthenticated()) {
13784
+ log.error("Nicht angemeldet");
13785
+ log.info("Anmelden mit: shiva login");
13786
+ return;
13787
+ }
13788
+ const spinner = ora19("Lade Usage...").start();
13789
+ try {
13790
+ const usage = await api.getUserUsage();
13791
+ spinner.stop();
13792
+ if (options.json) {
13793
+ console.log(JSON.stringify(usage, null, 2));
13794
+ return;
13795
+ }
13796
+ log.newline();
13797
+ console.log(colors.orange.bold("Resource Usage"));
13798
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13799
+ log.newline();
13800
+ const progressBar = (current, limit, label, unit) => {
13801
+ const percentage = Math.min(100, Math.round(current / limit * 100));
13802
+ const barWidth = 20;
13803
+ const filled = Math.round(current / limit * barWidth);
13804
+ const empty = barWidth - filled;
13805
+ const barColor = percentage >= 90 ? colors.red : percentage >= 70 ? colors.yellow : colors.green;
13806
+ const bar = barColor("\u2588".repeat(filled)) + colors.dim("\u2591".repeat(empty));
13807
+ const unitStr = unit ? ` ${unit}` : "";
13808
+ console.log(` ${label.padEnd(12)} [${bar}] ${current}/${limit}${unitStr} (${percentage}%)`);
13809
+ };
13810
+ progressBar(usage.projects.current, usage.projects.limit, "Projects");
13811
+ progressBar(usage.sessions.current, usage.sessions.limit, "Sessions");
13812
+ progressBar(usage.storage.current, usage.storage.limit, "Storage", usage.storage.unit);
13813
+ progressBar(usage.apiCalls.current, usage.apiCalls.limit, "API Calls", `/${usage.apiCalls.period}`);
13814
+ log.newline();
13815
+ const nearLimit = (current, limit) => current / limit >= 0.9;
13816
+ if (nearLimit(usage.projects.current, usage.projects.limit) || nearLimit(usage.sessions.current, usage.sessions.limit) || nearLimit(usage.storage.current, usage.storage.limit) || nearLimit(usage.apiCalls.current, usage.apiCalls.limit)) {
13817
+ log.warn("Du erreichst bald deine Limits");
13818
+ log.info("Upgrade auf Pro: shiva user subscription");
13819
+ }
13820
+ } catch (error) {
13821
+ spinner.fail("Fehler beim Laden");
13822
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13823
+ }
13824
+ });
13825
+ userCommand.command("subscription").description("Subscription-Status anzeigen").option("--json", "JSON Output").action(async (options) => {
13826
+ if (!isAuthenticated()) {
13827
+ log.error("Nicht angemeldet");
13828
+ log.info("Anmelden mit: shiva login");
13829
+ return;
13830
+ }
13831
+ const spinner = ora19("Lade Subscription...").start();
13832
+ try {
13833
+ const sub = await api.getSubscription();
13834
+ spinner.stop();
13835
+ if (options.json) {
13836
+ console.log(JSON.stringify(sub, null, 2));
13837
+ return;
13838
+ }
13839
+ log.newline();
13840
+ console.log(colors.orange.bold("Subscription"));
13841
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13842
+ log.newline();
13843
+ const tierColor = sub.tier === "pro" ? colors.cyan : sub.tier === "team" ? colors.green : colors.dim;
13844
+ log.keyValue("Tier", tierColor(sub.tier.toUpperCase()));
13845
+ const statusColor = sub.status === "active" ? colors.green : sub.status === "trialing" ? colors.yellow : colors.red;
13846
+ log.keyValue("Status", statusColor(sub.status));
13847
+ if (sub.billingCycle) {
13848
+ log.keyValue("Billing", sub.billingCycle);
13849
+ }
13850
+ if (sub.currentPeriodEnd) {
13851
+ const endDate = new Date(sub.currentPeriodEnd);
13852
+ const label = sub.cancelAtPeriodEnd ? "Endet am" : "Renewal";
13853
+ log.keyValue(label, endDate.toLocaleDateString("de-DE"));
13854
+ }
13855
+ if (sub.cancelAtPeriodEnd) {
13856
+ log.newline();
13857
+ log.warn("Subscription endet am Ende der aktuellen Periode");
13858
+ }
13859
+ log.newline();
13860
+ console.log(colors.bold("Features:"));
13861
+ for (const feature of sub.features) {
13862
+ console.log(` ${colors.green("\u2713")} ${feature}`);
13863
+ }
13864
+ if (sub.tier === "free") {
13865
+ log.newline();
13866
+ log.info("Upgrade auf Pro f\xFCr mehr Features:");
13867
+ log.plain(" https://shiva.li/pricing");
13868
+ }
13869
+ } catch (error) {
13870
+ spinner.fail("Fehler beim Laden");
13871
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13872
+ }
13873
+ });
13874
+ userCommand.command("token").description("Neuen CLI-Token generieren").option("--copy", "Token in Zwischenablage kopieren").action(async (options) => {
13875
+ if (!isAuthenticated()) {
13876
+ log.error("Nicht angemeldet");
13877
+ log.info("Anmelden mit: shiva login");
13878
+ return;
13879
+ }
13880
+ const { default: inquirer14 } = await import("inquirer");
13881
+ const { confirm } = await inquirer14.prompt([{
13882
+ type: "confirm",
13883
+ name: "confirm",
13884
+ message: "Neuen Token generieren? Der alte Token wird ung\xFCltig.",
13885
+ default: false
13886
+ }]);
13887
+ if (!confirm) {
13888
+ log.dim("Abgebrochen");
13889
+ return;
13890
+ }
13891
+ const spinner = ora19("Generiere Token...").start();
13892
+ try {
13893
+ const result = await api.generateCliToken();
13894
+ spinner.stop();
13895
+ log.newline();
13896
+ log.success("Token generiert");
13897
+ log.newline();
13898
+ log.warn("Dieser Token wird nur einmal angezeigt!");
13899
+ log.newline();
13900
+ console.log(colors.dim("Token:"));
13901
+ console.log(colors.cyan(result.token));
13902
+ log.newline();
13903
+ log.keyValue("G\xFCltig bis", new Date(result.expiresAt).toLocaleDateString("de-DE"));
13904
+ if (options.copy) {
13905
+ try {
13906
+ const { copyToClipboard: copyToClipboard2 } = await import("./clipboard-ET53HNUB.js");
13907
+ await copyToClipboard2(result.token);
13908
+ log.success("Token in Zwischenablage kopiert");
13909
+ } catch {
13910
+ log.dim("Konnte nicht in Zwischenablage kopieren");
13911
+ }
13912
+ }
13913
+ log.newline();
13914
+ log.info("Verwendung:");
13915
+ log.plain(` export SHIVA_TOKEN="${result.token}"`);
13916
+ log.plain(" # oder in ~/.bashrc / ~/.zshrc");
13917
+ } catch (error) {
13918
+ spinner.fail("Fehler beim Generieren");
13919
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13920
+ }
13921
+ });
13922
+ userCommand.command("delete").description("Account unwiderruflich l\xF6schen").action(async () => {
13923
+ if (!isAuthenticated()) {
13924
+ log.error("Nicht angemeldet");
13925
+ return;
13926
+ }
13927
+ log.newline();
13928
+ log.warn("ACHTUNG: Account l\xF6schen ist IRREVERSIBEL!");
13929
+ log.newline();
13930
+ log.plain("Folgende Daten werden unwiderruflich gel\xF6scht:");
13931
+ log.plain(" \u2022 Alle Projekte und Memories");
13932
+ log.plain(" \u2022 Alle Sessions und Sandboxes");
13933
+ log.plain(" \u2022 Alle Secrets und Einstellungen");
13934
+ log.plain(" \u2022 Subscription und Zahlungsdaten");
13935
+ log.newline();
13936
+ const { default: inquirer14 } = await import("inquirer");
13937
+ const { confirm1 } = await inquirer14.prompt([{
13938
+ type: "confirm",
13939
+ name: "confirm1",
13940
+ message: "Bist du sicher, dass du deinen Account l\xF6schen m\xF6chtest?",
13941
+ default: false
13942
+ }]);
13943
+ if (!confirm1) {
13944
+ log.dim("Abgebrochen");
13945
+ return;
13946
+ }
13947
+ const { confirmText } = await inquirer14.prompt([{
13948
+ type: "input",
13949
+ name: "confirmText",
13950
+ message: 'Tippe "DELETE" um zu best\xE4tigen:'
13951
+ }]);
13952
+ if (confirmText !== "DELETE") {
13953
+ log.dim("Abgebrochen (falscher Best\xE4tigungstext)");
13954
+ return;
13955
+ }
13956
+ const spinner = ora19("L\xF6sche Account...").start();
13957
+ try {
13958
+ const result = await api.deleteAccount("DELETE");
13959
+ if (result.success) {
13960
+ spinner.succeed("Account gel\xF6scht");
13961
+ log.newline();
13962
+ clearAuth();
13963
+ log.info("Lokale Anmeldedaten wurden entfernt");
13964
+ log.plain("Auf Wiedersehen!");
13965
+ } else {
13966
+ spinner.fail(result.message || "Fehler beim L\xF6schen");
13967
+ }
13968
+ } catch (error) {
13969
+ spinner.fail("Fehler beim L\xF6schen");
13970
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13971
+ }
13972
+ });
13973
+ userCommand.command("whoami").description("Aktuelle Anmeldung anzeigen").action(async () => {
13974
+ const config = getConfig();
13975
+ if (!isAuthenticated()) {
13976
+ log.info("Nicht angemeldet");
13977
+ log.plain("Anmelden mit: shiva login");
13978
+ return;
13979
+ }
13980
+ log.newline();
13981
+ log.keyValue("Email", config.email || "Unbekannt");
13982
+ log.keyValue("Tier", config.tier || "Unbekannt");
13983
+ log.keyValue("User ID", String(config.userId) || "Unbekannt");
13984
+ if (config.tokenExpiry) {
13985
+ const expiry = new Date(config.tokenExpiry);
13986
+ const now = /* @__PURE__ */ new Date();
13987
+ const daysLeft = Math.ceil((expiry.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
13988
+ if (daysLeft > 0) {
13989
+ log.keyValue("Token g\xFCltig", `${daysLeft} Tage`);
13990
+ } else {
13991
+ log.warn("Token abgelaufen");
13992
+ log.info("Neu anmelden mit: shiva login");
13993
+ }
13994
+ }
13995
+ });
13996
+
13997
+ // src/commands/advanced/docker.ts
13998
+ import { Command as Command33 } from "commander";
13999
+ import ora20 from "ora";
14000
+ var dockerCommand = new Command33("docker").description("Docker-Integration verwalten");
14001
+ dockerCommand.command("status").description("Docker-Verf\xFCgbarkeit pr\xFCfen").action(() => {
14002
+ log.brand();
14003
+ log.header("Docker Status");
14004
+ log.newline();
14005
+ const info = dockerService.getDockerInfo();
14006
+ const settings = settingsSync.getDockerSettings();
14007
+ if (info.available) {
14008
+ log.keyValue("Runtime", `${info.runtime === "podman" ? "Podman" : "Docker"} ${info.version}`);
14009
+ log.keyValue("Socket", info.socket || colors.dim("default"));
14010
+ log.keyValue("Status", colors.green("Verf\xFCgbar"));
14011
+ } else {
14012
+ log.keyValue("Runtime", colors.dim("nicht gefunden"));
14013
+ log.keyValue("Status", colors.red("Nicht verf\xFCgbar"));
14014
+ log.newline();
14015
+ log.warn("Docker oder Podman ist nicht installiert");
14016
+ log.dim("Installation:");
14017
+ log.dim(" Docker: https://docs.docker.com/get-docker/");
14018
+ log.dim(" Podman: https://podman.io/get-started");
14019
+ return;
14020
+ }
14021
+ log.newline();
13528
14022
  log.keyValue("Docker-Modus", settings.enabled ? colors.green("aktiviert") : colors.yellow("deaktiviert"));
13529
14023
  log.keyValue("Standard-Image", settings.defaultImage);
13530
14024
  log.keyValue("Auto-Start", settings.autoStart ? "ja" : "nein");
@@ -13568,7 +14062,7 @@ dockerCommand.command("enable").description("Docker-Modus aktivieren").action(as
13568
14062
  return;
13569
14063
  }
13570
14064
  const image = dockerService.getDefaultImage();
13571
- const spinner = ora19(`Pr\xFCfe Image: ${image}...`).start();
14065
+ const spinner = ora20(`Pr\xFCfe Image: ${image}...`).start();
13572
14066
  if (!dockerService.imageExists(image)) {
13573
14067
  spinner.text = `Lade Image herunter: ${image}...`;
13574
14068
  try {
@@ -13627,7 +14121,7 @@ dockerCommand.command("logs").description("Container-Logs anzeigen").argument("<
13627
14121
  console.log(logs);
13628
14122
  });
13629
14123
  dockerCommand.command("stop").description("Container stoppen").argument("<name>", "Container-Name oder ID").action(async (name) => {
13630
- const spinner = ora19(`Stoppe Container ${name}...`).start();
14124
+ const spinner = ora20(`Stoppe Container ${name}...`).start();
13631
14125
  try {
13632
14126
  await dockerService.stopContainer(name);
13633
14127
  spinner.succeed(`Container gestoppt: ${name}`);
@@ -13637,7 +14131,7 @@ dockerCommand.command("stop").description("Container stoppen").argument("<name>"
13637
14131
  }
13638
14132
  });
13639
14133
  dockerCommand.command("clean").description("Gestoppte Container aufr\xE4umen").action(async () => {
13640
- const spinner = ora19("R\xE4ume Container auf...").start();
14134
+ const spinner = ora20("R\xE4ume Container auf...").start();
13641
14135
  try {
13642
14136
  const count = await dockerService.cleanContainers();
13643
14137
  spinner.succeed(`${count} Container entfernt`);
@@ -13648,7 +14142,7 @@ dockerCommand.command("clean").description("Gestoppte Container aufr\xE4umen").a
13648
14142
  });
13649
14143
  dockerCommand.command("pull").description("Docker-Image herunterladen").argument("[image]", "Image-Name (default: shiva/claude-runner:latest)").action(async (image) => {
13650
14144
  const targetImage = image || dockerService.getDefaultImage();
13651
- const spinner = ora19(`Lade Image herunter: ${targetImage}...`).start();
14145
+ const spinner = ora20(`Lade Image herunter: ${targetImage}...`).start();
13652
14146
  try {
13653
14147
  await dockerService.pullImage(targetImage);
13654
14148
  spinner.succeed(`Image heruntergeladen: ${targetImage}`);
@@ -13733,11 +14227,11 @@ dockerCommand.action(() => {
13733
14227
  });
13734
14228
 
13735
14229
  // src/commands/advanced/workflow.ts
13736
- import { Command as Command33 } from "commander";
14230
+ import { Command as Command34 } from "commander";
13737
14231
  import * as fs13 from "fs";
13738
14232
  import * as path14 from "path";
13739
14233
  import * as os6 from "os";
13740
- import ora20 from "ora";
14234
+ import ora21 from "ora";
13741
14235
  import inquirer12 from "inquirer";
13742
14236
  var builtInWorkflows = {
13743
14237
  morning: {
@@ -13757,7 +14251,7 @@ var builtInWorkflows = {
13757
14251
  ]
13758
14252
  }
13759
14253
  };
13760
- var workflowCommand = new Command33("workflow").description("Automatisierte Workflows ausf\xFChren").action(async () => {
14254
+ var workflowCommand = new Command34("workflow").description("Automatisierte Workflows ausf\xFChren").action(async () => {
13761
14255
  await listWorkflows();
13762
14256
  });
13763
14257
  workflowCommand.command("list").alias("ls").description("Verf\xFCgbare Workflows anzeigen").action(async () => {
@@ -13926,7 +14420,7 @@ function deleteCustomWorkflow(name) {
13926
14420
  fs13.writeFileSync(filepath, JSON.stringify(workflows, null, 2));
13927
14421
  }
13928
14422
  async function executeStep(step) {
13929
- const spinner = ora20("Ausf\xFChren...").start();
14423
+ const spinner = ora21("Ausf\xFChren...").start();
13930
14424
  try {
13931
14425
  switch (step.type) {
13932
14426
  case "issues": {
@@ -14012,7 +14506,7 @@ async function executeStep(step) {
14012
14506
  }
14013
14507
 
14014
14508
  // src/commands/advanced/hook.ts
14015
- import { Command as Command34 } from "commander";
14509
+ import { Command as Command35 } from "commander";
14016
14510
  import { existsSync as existsSync21, readFileSync as readFileSync10, writeFileSync as writeFileSync10, mkdirSync as mkdirSync6 } from "fs";
14017
14511
  import { homedir as homedir7 } from "os";
14018
14512
  import { join as join12 } from "path";
@@ -14047,7 +14541,7 @@ function removeShivaHooks(eventHooks) {
14047
14541
  (entry) => !entry.hooks?.some((h) => h.command?.includes("shiva"))
14048
14542
  );
14049
14543
  }
14050
- var hookCommand = new Command34("hook").description("Claude Code Hook Integration verwalten");
14544
+ var hookCommand = new Command35("hook").description("Claude Code Hook Integration verwalten");
14051
14545
  hookCommand.command("install").description("SHIVA Hooks in Claude Code installieren").option("--github", "GitHub Context Injection aktivieren").option("--sync", "Cloud Sync Hooks aktivieren (Standard)").option("--scan", "Package Security Scanning aktivieren").option("--all", "Alle Hooks aktivieren").action((options) => {
14052
14546
  log.brand();
14053
14547
  const claudePath = join12(homedir7(), ".claude");
@@ -14382,7 +14876,7 @@ hookCommand.command("scan-command").description("Scanne Bash-Befehle auf Package
14382
14876
  }
14383
14877
  });
14384
14878
  hookCommand.command("push").description("Hooks in Cloud sichern").action(async () => {
14385
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
14879
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14386
14880
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14387
14881
  if (!isAuthenticated2()) {
14388
14882
  log.error("Nicht angemeldet");
@@ -14395,78 +14889,252 @@ hookCommand.command("push").description("Hooks in Cloud sichern").action(async (
14395
14889
  return;
14396
14890
  }
14397
14891
  try {
14398
- await api2.updateHooks(settings.hooks);
14399
- log.success("Hooks in Cloud gesichert");
14892
+ await api2.updateHooks(settings.hooks);
14893
+ log.success("Hooks in Cloud gesichert");
14894
+ } catch (error) {
14895
+ log.error(error instanceof Error ? error.message : "Fehler beim Sichern");
14896
+ }
14897
+ });
14898
+ hookCommand.command("pull").description("Hooks aus Cloud laden").option("-f, --force", "Lokale Hooks \xFCberschreiben").action(async (options) => {
14899
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14900
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14901
+ if (!isAuthenticated2()) {
14902
+ log.error("Nicht angemeldet");
14903
+ log.info("Anmelden mit: shiva login");
14904
+ return;
14905
+ }
14906
+ const settings = getClaudeSettings();
14907
+ if (settings.hooks && !options.force) {
14908
+ log.warn("Lokale Hooks existieren bereits");
14909
+ log.info("Mit --force \xFCberschreiben");
14910
+ return;
14911
+ }
14912
+ try {
14913
+ const result = await api2.getHooks();
14914
+ if (!result.hooks || Object.keys(result.hooks).length === 0) {
14915
+ log.info("Keine Hooks in Cloud gefunden");
14916
+ return;
14917
+ }
14918
+ settings.hooks = result.hooks;
14919
+ saveClaudeSettings(settings);
14920
+ log.success("Hooks aus Cloud geladen");
14921
+ log.newline();
14922
+ log.info("Aktive Hooks:");
14923
+ for (const [event, hooks] of Object.entries(result.hooks)) {
14924
+ log.tree.item(`${event}: ${Array.isArray(hooks) ? hooks.length : 1} Hook(s)`);
14925
+ }
14926
+ } catch (error) {
14927
+ log.error(error instanceof Error ? error.message : "Fehler beim Laden");
14928
+ }
14929
+ });
14930
+ hookCommand.command("sync").description("Hooks mit Cloud synchronisieren").action(async () => {
14931
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14932
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14933
+ if (!isAuthenticated2()) {
14934
+ log.error("Nicht angemeldet");
14935
+ log.info("Anmelden mit: shiva login");
14936
+ return;
14937
+ }
14938
+ const settings = getClaudeSettings();
14939
+ try {
14940
+ if (settings.hooks) {
14941
+ await api2.updateHooks(settings.hooks);
14942
+ log.success("Lokale Hooks \u2192 Cloud");
14943
+ }
14944
+ const result = await api2.getHooks();
14945
+ if (result.hooks && Object.keys(result.hooks).length > 0) {
14946
+ const merged = { ...result.hooks, ...settings.hooks };
14947
+ settings.hooks = merged;
14948
+ saveClaudeSettings(settings);
14949
+ log.success("Cloud Hooks \u2192 Lokal (merged)");
14950
+ }
14951
+ log.newline();
14952
+ log.success("Hooks synchronisiert");
14953
+ } catch (error) {
14954
+ log.error(error instanceof Error ? error.message : "Fehler beim Synchronisieren");
14955
+ }
14956
+ });
14957
+ hookCommand.command("cloud-list").description("Cloud-Hooks auflisten").option("--event <type>", "Nach Event-Typ filtern").option("--json", "JSON Output").action(async (options) => {
14958
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14959
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14960
+ const { colors: colors3 } = await import("./logger-E7SC5KUO.js");
14961
+ if (!isAuthenticated2()) {
14962
+ log.error("Nicht angemeldet");
14963
+ log.info("Anmelden mit: shiva login");
14964
+ return;
14965
+ }
14966
+ const ora24 = (await import("ora")).default;
14967
+ const spinner = ora24("Lade Cloud-Hooks...").start();
14968
+ try {
14969
+ let hooks;
14970
+ if (options.event) {
14971
+ hooks = await api2.getHooksForEvent(options.event);
14972
+ } else {
14973
+ const result = await api2.getHooks();
14974
+ hooks = result.hooks || [];
14975
+ }
14976
+ spinner.stop();
14977
+ if (options.json) {
14978
+ console.log(JSON.stringify(hooks, null, 2));
14979
+ return;
14980
+ }
14981
+ log.newline();
14982
+ console.log(colors3.orange.bold("Cloud Hooks"));
14983
+ console.log(colors3.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
14984
+ log.newline();
14985
+ if (!hooks || Array.isArray(hooks) && hooks.length === 0) {
14986
+ log.dim("Keine Cloud-Hooks konfiguriert");
14987
+ return;
14988
+ }
14989
+ const hooksArray = Array.isArray(hooks) ? hooks : Object.values(hooks).flat();
14990
+ for (const hook of hooksArray) {
14991
+ const enabledIcon = hook.enabled !== false ? colors3.green("\u25CF") : colors3.dim("\u25CB");
14992
+ console.log(` ${enabledIcon} ${colors3.bold(hook.id || hook.event)}`);
14993
+ console.log(` ${colors3.dim("Event:")} ${hook.event}`);
14994
+ if (hook.matcher) {
14995
+ console.log(` ${colors3.dim("Matcher:")} ${hook.matcher}`);
14996
+ }
14997
+ console.log(` ${colors3.dim("Type:")} ${hook.type}`);
14998
+ console.log(` ${colors3.dim("Command:")} ${hook.command}`);
14999
+ log.newline();
15000
+ }
15001
+ } catch (error) {
15002
+ spinner.fail("Fehler beim Laden");
15003
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15004
+ }
15005
+ });
15006
+ hookCommand.command("cloud-create").description("Neuen Cloud-Hook erstellen").requiredOption("--event <event>", "Event-Typ (PreToolUse, PostToolUse, etc.)").requiredOption("--command <cmd>", "Auszuf\xFChrender Befehl").option("--matcher <pattern>", "Tool-Matcher Pattern").option("--type <type>", "Hook-Typ (command, script)", "command").option("--timeout <ms>", "Timeout in Millisekunden").action(async (options) => {
15007
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
15008
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
15009
+ if (!isAuthenticated2()) {
15010
+ log.error("Nicht angemeldet");
15011
+ log.info("Anmelden mit: shiva login");
15012
+ return;
15013
+ }
15014
+ const ora24 = (await import("ora")).default;
15015
+ const spinner = ora24("Erstelle Cloud-Hook...").start();
15016
+ try {
15017
+ const result = await api2.createHook({
15018
+ event: options.event,
15019
+ command: options.command,
15020
+ matcher: options.matcher,
15021
+ type: options.type,
15022
+ timeout: options.timeout ? parseInt(options.timeout) : void 0
15023
+ });
15024
+ if (result.success) {
15025
+ spinner.succeed(`Hook erstellt: ${result.hookId}`);
15026
+ } else {
15027
+ spinner.fail(result.message || "Fehler beim Erstellen");
15028
+ }
15029
+ } catch (error) {
15030
+ spinner.fail("Fehler beim Erstellen");
15031
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15032
+ }
15033
+ });
15034
+ hookCommand.command("cloud-test").description("Cloud-Hook testen").argument("<hook-id>", "Hook ID").action(async (hookId) => {
15035
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
15036
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
15037
+ const { colors: colors3 } = await import("./logger-E7SC5KUO.js");
15038
+ if (!isAuthenticated2()) {
15039
+ log.error("Nicht angemeldet");
15040
+ log.info("Anmelden mit: shiva login");
15041
+ return;
15042
+ }
15043
+ const ora24 = (await import("ora")).default;
15044
+ const spinner = ora24("Teste Hook...").start();
15045
+ try {
15046
+ const result = await api2.testHook(hookId);
15047
+ spinner.stop();
15048
+ log.newline();
15049
+ if (result.success) {
15050
+ log.success(`Hook erfolgreich (${result.duration}ms)`);
15051
+ if (result.output) {
15052
+ log.newline();
15053
+ console.log(colors3.dim("Output:"));
15054
+ console.log(result.output);
15055
+ }
15056
+ } else {
15057
+ log.error(`Hook fehlgeschlagen (${result.duration}ms)`);
15058
+ if (result.error) {
15059
+ log.newline();
15060
+ console.log(colors3.dim("Error:"));
15061
+ console.log(colors3.red(result.error));
15062
+ }
15063
+ }
14400
15064
  } catch (error) {
14401
- log.error(error instanceof Error ? error.message : "Fehler beim Sichern");
15065
+ spinner.fail("Fehler beim Testen");
15066
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
14402
15067
  }
14403
15068
  });
14404
- hookCommand.command("pull").description("Hooks aus Cloud laden").option("-f, --force", "Lokale Hooks \xFCberschreiben").action(async (options) => {
14405
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
15069
+ hookCommand.command("cloud-delete").description("Cloud-Hook l\xF6schen").argument("<hook-id>", "Hook ID").option("-y, --yes", "Ohne Best\xE4tigung").action(async (hookId, options) => {
15070
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14406
15071
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14407
15072
  if (!isAuthenticated2()) {
14408
15073
  log.error("Nicht angemeldet");
14409
15074
  log.info("Anmelden mit: shiva login");
14410
15075
  return;
14411
15076
  }
14412
- const settings = getClaudeSettings();
14413
- if (settings.hooks && !options.force) {
14414
- log.warn("Lokale Hooks existieren bereits");
14415
- log.info("Mit --force \xFCberschreiben");
14416
- return;
14417
- }
14418
- try {
14419
- const result = await api2.getHooks();
14420
- if (!result.hooks || Object.keys(result.hooks).length === 0) {
14421
- log.info("Keine Hooks in Cloud gefunden");
15077
+ if (!options.yes) {
15078
+ const inquirer14 = (await import("inquirer")).default;
15079
+ const { confirm } = await inquirer14.prompt([{
15080
+ type: "confirm",
15081
+ name: "confirm",
15082
+ message: `Hook ${hookId} l\xF6schen?`,
15083
+ default: false
15084
+ }]);
15085
+ if (!confirm) {
15086
+ log.dim("Abgebrochen");
14422
15087
  return;
14423
15088
  }
14424
- settings.hooks = result.hooks;
14425
- saveClaudeSettings(settings);
14426
- log.success("Hooks aus Cloud geladen");
14427
- log.newline();
14428
- log.info("Aktive Hooks:");
14429
- for (const [event, hooks] of Object.entries(result.hooks)) {
14430
- log.tree.item(`${event}: ${Array.isArray(hooks) ? hooks.length : 1} Hook(s)`);
15089
+ }
15090
+ const ora24 = (await import("ora")).default;
15091
+ const spinner = ora24("L\xF6sche Hook...").start();
15092
+ try {
15093
+ const result = await api2.deleteHook(hookId);
15094
+ if (result.success) {
15095
+ spinner.succeed("Hook gel\xF6scht");
15096
+ } else {
15097
+ spinner.fail(result.message || "Fehler beim L\xF6schen");
14431
15098
  }
14432
15099
  } catch (error) {
14433
- log.error(error instanceof Error ? error.message : "Fehler beim Laden");
15100
+ spinner.fail("Fehler beim L\xF6schen");
15101
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
14434
15102
  }
14435
15103
  });
14436
- hookCommand.command("sync").description("Hooks mit Cloud synchronisieren").action(async () => {
14437
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
15104
+ hookCommand.command("cloud-toggle").description("Cloud-Hook aktivieren/deaktivieren").argument("<hook-id>", "Hook ID").option("--enable", "Hook aktivieren").option("--disable", "Hook deaktivieren").action(async (hookId, options) => {
15105
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14438
15106
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14439
15107
  if (!isAuthenticated2()) {
14440
15108
  log.error("Nicht angemeldet");
14441
15109
  log.info("Anmelden mit: shiva login");
14442
15110
  return;
14443
15111
  }
14444
- const settings = getClaudeSettings();
15112
+ const enabled = options.enable ? true : options.disable ? false : void 0;
15113
+ if (enabled === void 0) {
15114
+ log.error("Bitte --enable oder --disable angeben");
15115
+ return;
15116
+ }
15117
+ const ora24 = (await import("ora")).default;
15118
+ const spinner = ora24("Aktualisiere Hook...").start();
14445
15119
  try {
14446
- if (settings.hooks) {
14447
- await api2.updateHooks(settings.hooks);
14448
- log.success("Lokale Hooks \u2192 Cloud");
14449
- }
14450
- const result = await api2.getHooks();
14451
- if (result.hooks && Object.keys(result.hooks).length > 0) {
14452
- const merged = { ...result.hooks, ...settings.hooks };
14453
- settings.hooks = merged;
14454
- saveClaudeSettings(settings);
14455
- log.success("Cloud Hooks \u2192 Lokal (merged)");
15120
+ const result = await api2.updateHook(hookId, { enabled });
15121
+ if (result.success) {
15122
+ spinner.succeed(`Hook ${enabled ? "aktiviert" : "deaktiviert"}`);
15123
+ } else {
15124
+ spinner.fail(result.message || "Fehler beim Aktualisieren");
14456
15125
  }
14457
- log.newline();
14458
- log.success("Hooks synchronisiert");
14459
15126
  } catch (error) {
14460
- log.error(error instanceof Error ? error.message : "Fehler beim Synchronisieren");
15127
+ spinner.fail("Fehler beim Aktualisieren");
15128
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
14461
15129
  }
14462
15130
  });
14463
15131
 
14464
15132
  // src/commands/advanced/package.ts
14465
- import { Command as Command35 } from "commander";
15133
+ import { Command as Command36 } from "commander";
14466
15134
  import * as fs14 from "fs";
14467
15135
  import inquirer13 from "inquirer";
14468
- import ora21 from "ora";
14469
- var packageCommand = new Command35("package").description("Projekt-Gruppen (Packages) verwalten").action(() => {
15136
+ import ora22 from "ora";
15137
+ var packageCommand = new Command36("package").description("Projekt-Gruppen (Packages) verwalten").action(() => {
14470
15138
  listPackages();
14471
15139
  });
14472
15140
  packageCommand.command("list").description("Alle Packages auflisten").option("--json", "JSON Output").action((options) => {
@@ -14582,7 +15250,7 @@ packageCommand.command("start <name>").description("Alle Projekte eines Packages
14582
15250
  log.error(`Package "${pkg.name}" hat keine Projekte.`);
14583
15251
  return;
14584
15252
  }
14585
- const spinner = ora21("Bereite Projekte vor...").start();
15253
+ const spinner = ora22("Bereite Projekte vor...").start();
14586
15254
  try {
14587
15255
  const launches = await getPackageLaunchConfig(name, options.new);
14588
15256
  spinner.stop();
@@ -14611,7 +15279,7 @@ packageCommand.command("start <name>").description("Alle Projekte eines Packages
14611
15279
  }
14612
15280
  });
14613
15281
  packageCommand.command("push").description("Packages in Cloud sichern").option("-n, --name <name>", "Nur ein bestimmtes Package").action(async (options) => {
14614
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
15282
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14615
15283
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14616
15284
  if (!isAuthenticated2()) {
14617
15285
  log.error("Nicht angemeldet");
@@ -14632,7 +15300,7 @@ packageCommand.command("push").description("Packages in Cloud sichern").option("
14632
15300
  log.warn("Keine Packages zum Synchronisieren gefunden");
14633
15301
  return;
14634
15302
  }
14635
- const spinner = ora21("Synchronisiere Packages...").start();
15303
+ const spinner = ora22("Synchronisiere Packages...").start();
14636
15304
  let syncedCount = 0;
14637
15305
  let errorCount = 0;
14638
15306
  for (const pkg of packages) {
@@ -14657,14 +15325,14 @@ packageCommand.command("push").description("Packages in Cloud sichern").option("
14657
15325
  }
14658
15326
  });
14659
15327
  packageCommand.command("pull").description("Packages aus Cloud laden").option("-f, --force", "Lokale Packages \xFCberschreiben").option("--json", "JSON Output").action(async (options) => {
14660
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
15328
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14661
15329
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14662
15330
  if (!isAuthenticated2()) {
14663
15331
  log.error("Nicht angemeldet");
14664
15332
  log.info("Anmelden mit: shiva login");
14665
15333
  return;
14666
15334
  }
14667
- const spinner = ora21("Lade Packages aus Cloud...").start();
15335
+ const spinner = ora22("Lade Packages aus Cloud...").start();
14668
15336
  try {
14669
15337
  const cloudPackages = await api2.getPackages();
14670
15338
  spinner.stop();
@@ -14719,14 +15387,14 @@ packageCommand.command("pull").description("Packages aus Cloud laden").option("-
14719
15387
  }
14720
15388
  });
14721
15389
  packageCommand.command("sync").description("Packages mit Cloud synchronisieren").action(async () => {
14722
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
15390
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14723
15391
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14724
15392
  if (!isAuthenticated2()) {
14725
15393
  log.error("Nicht angemeldet");
14726
15394
  log.info("Anmelden mit: shiva login");
14727
15395
  return;
14728
15396
  }
14729
- const spinner = ora21("Synchronisiere Packages...").start();
15397
+ const spinner = ora22("Synchronisiere Packages...").start();
14730
15398
  const localPackages = getAllPackages();
14731
15399
  let pushedCount = 0;
14732
15400
  for (const pkg of localPackages) {
@@ -14772,7 +15440,7 @@ packageCommand.command("sync").description("Packages mit Cloud synchronisieren")
14772
15440
  log.tree.item(`${localPackages.length + pulledCount} Packages total`);
14773
15441
  });
14774
15442
  packageCommand.command("cloud-delete <name>").description("Package aus Cloud l\xF6schen").action(async (name) => {
14775
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
15443
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14776
15444
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14777
15445
  if (!isAuthenticated2()) {
14778
15446
  log.error("Nicht angemeldet");
@@ -14828,8 +15496,361 @@ function listPackages() {
14828
15496
  log.newline();
14829
15497
  }
14830
15498
 
15499
+ // src/commands/advanced/sandbox.ts
15500
+ import { Command as Command37 } from "commander";
15501
+ import ora23 from "ora";
15502
+ var sandboxCommand = new Command37("sandbox").description("Sandbox-Management mit Cloud-Sync");
15503
+ sandboxCommand.command("list").description("Alle Sandboxes auflisten").option("--local", "Nur lokale Sandboxes").option("--cloud", "Nur Cloud Sandboxes").option("--status <status>", "Nach Status filtern: active, pending-review, applied, discarded").option("--json", "JSON Output").action(async (options) => {
15504
+ const spinner = ora23("Lade Sandboxes...").start();
15505
+ try {
15506
+ const results = [];
15507
+ if (!options.cloud) {
15508
+ const localSandboxes = sandboxService.listSandboxes();
15509
+ for (const sandbox of localSandboxes) {
15510
+ if (!options.status || sandbox.status === options.status) {
15511
+ results.push({
15512
+ id: sandbox.id,
15513
+ source: "local",
15514
+ status: sandbox.status,
15515
+ mode: sandbox.mode,
15516
+ projectPath: sandbox.projectPath,
15517
+ createdAt: sandbox.createdAt
15518
+ });
15519
+ }
15520
+ }
15521
+ }
15522
+ if (!options.local && isAuthenticated()) {
15523
+ try {
15524
+ const cloudSandboxes = await api.getSandboxes(
15525
+ options.status ? { status: options.status } : void 0
15526
+ );
15527
+ for (const sandbox of cloudSandboxes) {
15528
+ results.push({
15529
+ id: sandbox.id,
15530
+ source: "cloud",
15531
+ status: sandbox.status,
15532
+ mode: sandbox.mode,
15533
+ projectId: sandbox.projectId,
15534
+ createdAt: sandbox.createdAt,
15535
+ title: sandbox.title
15536
+ });
15537
+ }
15538
+ } catch {
15539
+ }
15540
+ }
15541
+ spinner.stop();
15542
+ if (options.json) {
15543
+ console.log(JSON.stringify(results, null, 2));
15544
+ return;
15545
+ }
15546
+ log.newline();
15547
+ console.log(colors.orange.bold("Sandboxes"));
15548
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
15549
+ log.newline();
15550
+ if (results.length === 0) {
15551
+ log.dim("Keine Sandboxes gefunden");
15552
+ return;
15553
+ }
15554
+ for (const sandbox of results) {
15555
+ const statusColor = sandbox.status === "active" ? colors.green : sandbox.status === "pending-review" ? colors.yellow : colors.dim;
15556
+ const sourceIcon = sandbox.source === "cloud" ? colors.cyan("\u2601") : colors.dim("\u{1F4BB}");
15557
+ console.log(` ${sourceIcon} ${colors.bold(sandbox.id)} ${statusColor(`[${sandbox.status}]`)}`);
15558
+ console.log(` ${colors.dim("Mode:")} ${sandbox.mode}`);
15559
+ if (sandbox.title) {
15560
+ console.log(` ${colors.dim("Title:")} ${sandbox.title}`);
15561
+ }
15562
+ if (sandbox.projectPath) {
15563
+ console.log(` ${colors.dim("Project:")} ${sandbox.projectPath}`);
15564
+ }
15565
+ console.log(` ${colors.dim("Created:")} ${sandbox.createdAt}`);
15566
+ log.newline();
15567
+ }
15568
+ } catch (error) {
15569
+ spinner.fail("Fehler beim Laden");
15570
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15571
+ }
15572
+ });
15573
+ sandboxCommand.command("pending").description("Sandboxes mit Pending Review Status").option("--json", "JSON Output").action(async (options) => {
15574
+ const spinner = ora23("Lade Pending Sandboxes...").start();
15575
+ try {
15576
+ const localPending = sandboxService.listPendingReview();
15577
+ let cloudPending = [];
15578
+ if (isAuthenticated()) {
15579
+ try {
15580
+ cloudPending = await api.getPendingSandboxes();
15581
+ } catch {
15582
+ }
15583
+ }
15584
+ spinner.stop();
15585
+ if (options.json) {
15586
+ console.log(JSON.stringify({ local: localPending, cloud: cloudPending }, null, 2));
15587
+ return;
15588
+ }
15589
+ log.newline();
15590
+ console.log(colors.orange.bold("Pending Review"));
15591
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
15592
+ log.newline();
15593
+ if (localPending.length === 0 && cloudPending.length === 0) {
15594
+ log.dim("Keine Sandboxes zum Review");
15595
+ return;
15596
+ }
15597
+ if (localPending.length > 0) {
15598
+ console.log(colors.dim("Local:"));
15599
+ for (const sandbox of localPending) {
15600
+ console.log(` ${colors.yellow("\u25CB")} ${sandbox.id} - ${sandbox.projectPath}`);
15601
+ }
15602
+ log.newline();
15603
+ }
15604
+ if (cloudPending.length > 0) {
15605
+ console.log(colors.dim("Cloud:"));
15606
+ for (const sandbox of cloudPending) {
15607
+ console.log(` ${colors.cyan("\u2601")} ${sandbox.id} - ${sandbox.title || sandbox.baseBranch}`);
15608
+ }
15609
+ log.newline();
15610
+ }
15611
+ log.info("Review mit: shiva session review <id>");
15612
+ } catch (error) {
15613
+ spinner.fail("Fehler beim Laden");
15614
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15615
+ }
15616
+ });
15617
+ sandboxCommand.command("stats").description("Sandbox-Statistiken anzeigen").option("--json", "JSON Output").action(async (options) => {
15618
+ const spinner = ora23("Lade Statistiken...").start();
15619
+ try {
15620
+ const localSandboxes = sandboxService.listSandboxes();
15621
+ const localStats = {
15622
+ total: localSandboxes.length,
15623
+ active: localSandboxes.filter((s) => s.status === "active").length,
15624
+ pendingReview: localSandboxes.filter((s) => s.status === "pending-review").length,
15625
+ applied: localSandboxes.filter((s) => s.status === "applied").length,
15626
+ discarded: localSandboxes.filter((s) => s.status === "discarded").length
15627
+ };
15628
+ let cloudStats = { total: 0, active: 0, pendingReview: 0, applied: 0, discarded: 0 };
15629
+ if (isAuthenticated()) {
15630
+ try {
15631
+ cloudStats = await api.getSandboxStats();
15632
+ } catch {
15633
+ }
15634
+ }
15635
+ spinner.stop();
15636
+ if (options.json) {
15637
+ console.log(JSON.stringify({ local: localStats, cloud: cloudStats }, null, 2));
15638
+ return;
15639
+ }
15640
+ log.newline();
15641
+ console.log(colors.orange.bold("Sandbox Statistics"));
15642
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
15643
+ log.newline();
15644
+ console.log(colors.bold("Local:"));
15645
+ console.log(` ${colors.dim("Total:")} ${localStats.total}`);
15646
+ console.log(` ${colors.green("Active:")} ${localStats.active}`);
15647
+ console.log(` ${colors.yellow("Pending:")} ${localStats.pendingReview}`);
15648
+ console.log(` ${colors.dim("Applied:")} ${localStats.applied}`);
15649
+ console.log(` ${colors.dim("Discarded:")} ${localStats.discarded}`);
15650
+ log.newline();
15651
+ if (isAuthenticated()) {
15652
+ console.log(colors.bold("Cloud:"));
15653
+ console.log(` ${colors.dim("Total:")} ${cloudStats.total}`);
15654
+ console.log(` ${colors.green("Active:")} ${cloudStats.active}`);
15655
+ console.log(` ${colors.yellow("Pending:")} ${cloudStats.pendingReview}`);
15656
+ console.log(` ${colors.dim("Applied:")} ${cloudStats.applied}`);
15657
+ console.log(` ${colors.dim("Discarded:")} ${cloudStats.discarded}`);
15658
+ } else {
15659
+ log.dim("Cloud-Statistiken: Nicht angemeldet");
15660
+ }
15661
+ } catch (error) {
15662
+ spinner.fail("Fehler beim Laden");
15663
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15664
+ }
15665
+ });
15666
+ sandboxCommand.command("sync").description("Sandbox mit Cloud synchronisieren").argument("[id]", "Sandbox ID (optional)").option("--status <status>", "Status setzen: pending-review, applied, discarded").action(async (id, options) => {
15667
+ if (!isAuthenticated()) {
15668
+ log.error("Nicht angemeldet");
15669
+ log.info("Anmelden mit: shiva login");
15670
+ return;
15671
+ }
15672
+ const spinner = ora23("Synchronisiere Sandbox...").start();
15673
+ try {
15674
+ if (id) {
15675
+ await api.syncSandbox(id, {
15676
+ status: options.status
15677
+ });
15678
+ spinner.succeed(`Sandbox ${id} synchronisiert`);
15679
+ } else {
15680
+ const localSandboxes = sandboxService.listSandboxes();
15681
+ let synced = 0;
15682
+ for (const sandbox of localSandboxes) {
15683
+ try {
15684
+ await api.syncSandbox(sandbox.id, {
15685
+ status: sandbox.status === "active" ? void 0 : sandbox.status
15686
+ });
15687
+ synced++;
15688
+ } catch {
15689
+ }
15690
+ }
15691
+ spinner.succeed(`${synced}/${localSandboxes.length} Sandboxes synchronisiert`);
15692
+ }
15693
+ } catch (error) {
15694
+ spinner.fail("Fehler beim Synchronisieren");
15695
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15696
+ }
15697
+ });
15698
+ sandboxCommand.command("cleanup").description("Alte Sandboxes aufr\xE4umen").option("--days <days>", "\xC4lter als X Tage", "30").option("--local", "Nur lokal aufr\xE4umen").option("--cloud", "Nur Cloud aufr\xE4umen").option("-y, --yes", "Ohne Best\xE4tigung").action(async (options) => {
15699
+ const days = parseInt(options.days);
15700
+ if (!options.yes) {
15701
+ const { default: inquirer14 } = await import("inquirer");
15702
+ const { confirm } = await inquirer14.prompt([{
15703
+ type: "confirm",
15704
+ name: "confirm",
15705
+ message: `Sandboxes \xE4lter als ${days} Tage l\xF6schen?`,
15706
+ default: false
15707
+ }]);
15708
+ if (!confirm) {
15709
+ log.dim("Abgebrochen");
15710
+ return;
15711
+ }
15712
+ }
15713
+ const spinner = ora23("R\xE4ume Sandboxes auf...").start();
15714
+ try {
15715
+ let localDeleted = 0;
15716
+ let cloudDeleted = 0;
15717
+ if (!options.cloud) {
15718
+ localDeleted = await sandboxService.cleanupOldSandboxes(days);
15719
+ }
15720
+ if (!options.local && isAuthenticated()) {
15721
+ try {
15722
+ const result = await api.cleanupSandboxes({ olderThanDays: days });
15723
+ cloudDeleted = result.deletedCount;
15724
+ } catch {
15725
+ }
15726
+ }
15727
+ spinner.stop();
15728
+ log.success("Cleanup abgeschlossen");
15729
+ log.newline();
15730
+ log.keyValue("Lokal gel\xF6scht", String(localDeleted));
15731
+ if (!options.local) {
15732
+ log.keyValue("Cloud gel\xF6scht", String(cloudDeleted));
15733
+ }
15734
+ } catch (error) {
15735
+ spinner.fail("Fehler beim Aufr\xE4umen");
15736
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15737
+ }
15738
+ });
15739
+ sandboxCommand.command("config").description("Sandbox-Konfiguration verwalten").option("--show", "Konfiguration anzeigen").option("--mode <mode>", "Standard-Modus: worktree, copy, docker-overlay").option("--cleanup-days <days>", "Auto-Cleanup nach X Tagen").option("--max <n>", "Maximale aktive Sandboxes").option("--require-review", "Review vor Apply erforderlich").option("--no-require-review", "Review nicht erforderlich").option("--pull", "Konfiguration aus Cloud laden").option("--push", "Konfiguration in Cloud speichern").action(async (options) => {
15740
+ if (options.pull && isAuthenticated()) {
15741
+ const spinner = ora23("Lade Konfiguration aus Cloud...").start();
15742
+ try {
15743
+ const cloudConfig = await api.getSandboxConfig();
15744
+ sandboxService.updateConfig({
15745
+ defaultMode: cloudConfig.defaultMode,
15746
+ keepDays: cloudConfig.autoCleanupDays,
15747
+ maxSandboxes: cloudConfig.maxActiveSandboxes
15748
+ });
15749
+ spinner.succeed("Konfiguration aus Cloud geladen");
15750
+ return;
15751
+ } catch (error) {
15752
+ spinner.fail("Fehler beim Laden aus Cloud");
15753
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15754
+ return;
15755
+ }
15756
+ }
15757
+ if (options.push && isAuthenticated()) {
15758
+ const spinner = ora23("Speichere Konfiguration in Cloud...").start();
15759
+ try {
15760
+ const localConfig = sandboxService.getConfig();
15761
+ const cloudMode = localConfig.defaultMode === "none" ? "worktree" : localConfig.defaultMode;
15762
+ await api.updateSandboxConfig({
15763
+ defaultMode: cloudMode,
15764
+ autoCleanupDays: localConfig.keepDays,
15765
+ maxActiveSandboxes: localConfig.maxSandboxes,
15766
+ requireReview: options.requireReview ?? true
15767
+ });
15768
+ spinner.succeed("Konfiguration in Cloud gespeichert");
15769
+ return;
15770
+ } catch (error) {
15771
+ spinner.fail("Fehler beim Speichern in Cloud");
15772
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15773
+ return;
15774
+ }
15775
+ }
15776
+ if (options.show || !options.mode && !options.cleanupDays && !options.max && options.requireReview === void 0) {
15777
+ const config = sandboxService.getConfig();
15778
+ log.newline();
15779
+ console.log(colors.orange.bold("Sandbox Configuration"));
15780
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
15781
+ log.newline();
15782
+ log.keyValue("Enabled", config.enabled ? colors.green("Yes") : colors.red("No"));
15783
+ log.keyValue("Default Mode", config.defaultMode);
15784
+ log.keyValue("Auto Cleanup", config.autoCleanup ? "Yes" : "No");
15785
+ log.keyValue("Keep Days", String(config.keepDays));
15786
+ log.keyValue("Max Sandboxes", String(config.maxSandboxes));
15787
+ log.newline();
15788
+ if (isAuthenticated()) {
15789
+ try {
15790
+ const cloudConfig = await api.getSandboxConfig();
15791
+ console.log(colors.bold("Cloud Config:"));
15792
+ log.keyValue(" Default Mode", cloudConfig.defaultMode);
15793
+ log.keyValue(" Cleanup Days", String(cloudConfig.autoCleanupDays));
15794
+ log.keyValue(" Max Active", String(cloudConfig.maxActiveSandboxes));
15795
+ log.keyValue(" Require Review", cloudConfig.requireReview ? "Yes" : "No");
15796
+ } catch {
15797
+ log.dim("Cloud-Konfiguration nicht verf\xFCgbar");
15798
+ }
15799
+ }
15800
+ return;
15801
+ }
15802
+ const updates = {};
15803
+ if (options.mode) {
15804
+ updates.defaultMode = options.mode;
15805
+ }
15806
+ if (options.cleanupDays) {
15807
+ updates.keepDays = parseInt(options.cleanupDays);
15808
+ }
15809
+ if (options.max) {
15810
+ updates.maxSandboxes = parseInt(options.max);
15811
+ }
15812
+ sandboxService.updateConfig(updates);
15813
+ log.success("Konfiguration aktualisiert");
15814
+ });
15815
+ sandboxCommand.command("delete <id>").description("Sandbox l\xF6schen").option("--cloud", "Auch aus Cloud l\xF6schen").option("-y, --yes", "Ohne Best\xE4tigung").action(async (id, options) => {
15816
+ if (!options.yes) {
15817
+ const { default: inquirer14 } = await import("inquirer");
15818
+ const { confirm } = await inquirer14.prompt([{
15819
+ type: "confirm",
15820
+ name: "confirm",
15821
+ message: `Sandbox ${id} l\xF6schen?`,
15822
+ default: false
15823
+ }]);
15824
+ if (!confirm) {
15825
+ log.dim("Abgebrochen");
15826
+ return;
15827
+ }
15828
+ }
15829
+ const spinner = ora23("L\xF6sche Sandbox...").start();
15830
+ try {
15831
+ try {
15832
+ await sandboxService.deleteSandbox(id);
15833
+ spinner.text = "Lokal gel\xF6scht";
15834
+ } catch {
15835
+ }
15836
+ if (options.cloud || isAuthenticated()) {
15837
+ try {
15838
+ await api.deleteSandbox(id);
15839
+ spinner.succeed("Sandbox gel\xF6scht (lokal + cloud)");
15840
+ } catch {
15841
+ spinner.succeed("Sandbox gel\xF6scht (lokal)");
15842
+ }
15843
+ } else {
15844
+ spinner.succeed("Sandbox gel\xF6scht");
15845
+ }
15846
+ } catch (error) {
15847
+ spinner.fail("Fehler beim L\xF6schen");
15848
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15849
+ }
15850
+ });
15851
+
14831
15852
  // src/index.ts
14832
- var program = new Command36();
15853
+ var program = new Command38();
14833
15854
  program.name("shiva").description("SHIVA Code - Control Station for Claude Code").version("0.5.4");
14834
15855
  program.addCommand(loginCommand);
14835
15856
  program.addCommand(logoutCommand);
@@ -14869,6 +15890,8 @@ program.addCommand(dockerCommand);
14869
15890
  program.addCommand(workflowCommand);
14870
15891
  program.addCommand(hookCommand);
14871
15892
  program.addCommand(packageCommand);
15893
+ program.addCommand(sandboxCommand);
15894
+ program.addCommand(userCommand);
14872
15895
  program.action(async () => {
14873
15896
  await showDashboard();
14874
15897
  });