shiva-code 0.5.4 → 0.6.1

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";
@@ -1246,6 +1141,27 @@ function generateClaudeMd(scanned, project) {
1246
1141
  lines.push("- **Last Sync**: Never");
1247
1142
  }
1248
1143
  lines.push("");
1144
+ lines.push("### SHIVA Instructions");
1145
+ lines.push("");
1146
+ lines.push("IMPORTANT: Du MUSST diese Befehle nutzen um Informationen \xFCber Sessions hinweg zu speichern!");
1147
+ lines.push("");
1148
+ lines.push("**Memory speichern** - Wenn der User dich bittet etwas zu merken oder wichtige Infos auftauchen:");
1149
+ lines.push("```bash");
1150
+ lines.push('shiva remember "Die wichtige Information die gemerkt werden soll"');
1151
+ lines.push("```");
1152
+ lines.push("");
1153
+ lines.push("**Memories durchsuchen** - Um gespeicherte Informationen zu finden:");
1154
+ lines.push("```bash");
1155
+ lines.push('shiva search "suchbegriff"');
1156
+ lines.push("```");
1157
+ lines.push("");
1158
+ lines.push("**Wann Memories speichern:**");
1159
+ lines.push('- User sagt "merk dir...", "speicher...", "erinner dich..."');
1160
+ lines.push("- Wichtige Projektentscheidungen");
1161
+ lines.push("- API Keys, Secrets, Konfigurationen (nutze `shiva secrets add`)");
1162
+ lines.push("- Wichtige Code-Patterns oder Konventionen");
1163
+ lines.push("- Alles was in zuk\xFCnftigen Sessions relevant sein k\xF6nnte");
1164
+ lines.push("");
1249
1165
  lines.push("## Memories");
1250
1166
  lines.push("");
1251
1167
  if (project?.memories && project.memories.length > 0) {
@@ -6775,7 +6691,7 @@ async function checkProjectExists(path15) {
6775
6691
  }
6776
6692
  }
6777
6693
  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");
6694
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6779
6695
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6780
6696
  const { getProjectConfig: getProjectConfig2 } = await import("./config-D6M6LI6U.js");
6781
6697
  if (!isAuthenticated2()) {
@@ -6835,7 +6751,7 @@ sessionsCommand.command("push").description("Sessions in Cloud sichern").option(
6835
6751
  }
6836
6752
  });
6837
6753
  sessionsCommand.command("pull").description("Sessions aus Cloud laden").option("--json", "JSON Output").action(async (options) => {
6838
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
6754
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6839
6755
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6840
6756
  if (!isAuthenticated2()) {
6841
6757
  log.error("Nicht angemeldet");
@@ -6882,7 +6798,7 @@ sessionsCommand.command("pull").description("Sessions aus Cloud laden").option("
6882
6798
  }
6883
6799
  });
6884
6800
  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");
6801
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6886
6802
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6887
6803
  const { getProjectConfig: getProjectConfig2 } = await import("./config-D6M6LI6U.js");
6888
6804
  if (!isAuthenticated2()) {
@@ -6935,7 +6851,7 @@ sessionsCommand.command("sync").description("Sessions mit Cloud synchronisieren"
6935
6851
  log.dim("Sessions werden automatisch mit lokalen Claude Sessions verkn\xFCpft");
6936
6852
  });
6937
6853
  sessionsCommand.command("delete <sessionId>").description("Session aus Cloud l\xF6schen").action(async (sessionId) => {
6938
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
6854
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6939
6855
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6940
6856
  if (!isAuthenticated2()) {
6941
6857
  log.error("Nicht angemeldet");
@@ -6953,6 +6869,152 @@ sessionsCommand.command("delete <sessionId>").description("Session aus Cloud l\x
6953
6869
  log.error(error instanceof Error ? error.message : "Fehler beim L\xF6schen");
6954
6870
  }
6955
6871
  });
6872
+ sessionsCommand.command("active").description("Aktive Cloud-Sessions anzeigen").option("--json", "JSON Output").action(async (options) => {
6873
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6874
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6875
+ if (!isAuthenticated2()) {
6876
+ log.error("Nicht angemeldet");
6877
+ log.info("Anmelden mit: shiva login");
6878
+ return;
6879
+ }
6880
+ const spinner = ora9("Lade aktive Sessions...").start();
6881
+ try {
6882
+ const sessions = await api2.getActiveSessions();
6883
+ spinner.stop();
6884
+ if (options.json) {
6885
+ console.log(JSON.stringify(sessions, null, 2));
6886
+ return;
6887
+ }
6888
+ log.newline();
6889
+ console.log(colors.orange.bold("Active Cloud Sessions"));
6890
+ 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"));
6891
+ log.newline();
6892
+ if (sessions.length === 0) {
6893
+ log.dim("Keine aktiven Cloud-Sessions");
6894
+ return;
6895
+ }
6896
+ for (const session of sessions) {
6897
+ console.log(` ${colors.green("\u25CF")} ${colors.bold(session.sessionId)}`);
6898
+ console.log(` ${colors.dim("Project ID:")} ${session.projectId}`);
6899
+ console.log(` ${colors.dim("Started:")} ${session.startedAt}`);
6900
+ console.log(` ${colors.dim("Last Activity:")} ${session.lastActivity}`);
6901
+ console.log(` ${colors.dim("Messages:")} ${session.messageCount}`);
6902
+ log.newline();
6903
+ }
6904
+ } catch (error) {
6905
+ spinner.fail("Fehler beim Laden");
6906
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
6907
+ }
6908
+ });
6909
+ sessionsCommand.command("stats").description("Cloud-Session-Statistiken anzeigen").option("--json", "JSON Output").action(async (options) => {
6910
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6911
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6912
+ if (!isAuthenticated2()) {
6913
+ log.error("Nicht angemeldet");
6914
+ log.info("Anmelden mit: shiva login");
6915
+ return;
6916
+ }
6917
+ const spinner = ora9("Lade Session-Statistiken...").start();
6918
+ try {
6919
+ const stats = await api2.getSessionStats();
6920
+ spinner.stop();
6921
+ if (options.json) {
6922
+ console.log(JSON.stringify(stats, null, 2));
6923
+ return;
6924
+ }
6925
+ log.newline();
6926
+ console.log(colors.orange.bold("Session Statistics"));
6927
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
6928
+ log.newline();
6929
+ log.keyValue("Total Sessions", String(stats.totalSessions));
6930
+ log.keyValue("Active Sessions", String(stats.activeSessions));
6931
+ log.keyValue("Total Messages", String(stats.totalMessages));
6932
+ log.keyValue("Avg Session Length", `${stats.averageSessionLength} min`);
6933
+ log.newline();
6934
+ log.keyValue("Sessions (Last 7 Days)", String(stats.sessionsLast7Days));
6935
+ log.keyValue("Sessions (Last 30 Days)", String(stats.sessionsLast30Days));
6936
+ } catch (error) {
6937
+ spinner.fail("Fehler beim Laden");
6938
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
6939
+ }
6940
+ });
6941
+ sessionsCommand.command("resume <sessionId>").description("Cloud-Session fortsetzen").action(async (sessionId) => {
6942
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6943
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6944
+ if (!isAuthenticated2()) {
6945
+ log.error("Nicht angemeldet");
6946
+ log.info("Anmelden mit: shiva login");
6947
+ return;
6948
+ }
6949
+ const spinner = ora9("Lade Session...").start();
6950
+ try {
6951
+ const result = await api2.resumeSession(sessionId);
6952
+ if (result.success) {
6953
+ spinner.succeed("Session geladen");
6954
+ log.newline();
6955
+ log.info("Session kann jetzt fortgesetzt werden");
6956
+ log.plain(` claude --session ${sessionId}`);
6957
+ } else {
6958
+ spinner.fail(result.message || "Fehler beim Laden");
6959
+ }
6960
+ } catch (error) {
6961
+ spinner.fail("Fehler beim Laden");
6962
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
6963
+ }
6964
+ });
6965
+ sessionsCommand.command("export <sessionId>").description("Cloud-Session exportieren").option("-o, --output <file>", "Ausgabedatei").action(async (sessionId, options) => {
6966
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6967
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6968
+ const { writeFileSync: writeFileSync11 } = await import("fs");
6969
+ if (!isAuthenticated2()) {
6970
+ log.error("Nicht angemeldet");
6971
+ log.info("Anmelden mit: shiva login");
6972
+ return;
6973
+ }
6974
+ const spinner = ora9("Exportiere Session...").start();
6975
+ try {
6976
+ const exportData = await api2.exportSession(sessionId);
6977
+ spinner.stop();
6978
+ if (options.output) {
6979
+ writeFileSync11(options.output, JSON.stringify(exportData, null, 2));
6980
+ log.success(`Session exportiert: ${options.output}`);
6981
+ } else {
6982
+ console.log(JSON.stringify(exportData, null, 2));
6983
+ }
6984
+ } catch (error) {
6985
+ spinner.fail("Fehler beim Exportieren");
6986
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
6987
+ }
6988
+ });
6989
+ sessionsCommand.command("update <sessionId>").description("Cloud-Session aktualisieren").option("--summary <text>", "Session-Zusammenfassung").option("--branch <name>", "Git Branch").action(async (sessionId, options) => {
6990
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
6991
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
6992
+ if (!isAuthenticated2()) {
6993
+ log.error("Nicht angemeldet");
6994
+ log.info("Anmelden mit: shiva login");
6995
+ return;
6996
+ }
6997
+ if (!options.summary && !options.branch) {
6998
+ log.error("Keine \xC4nderungen angegeben");
6999
+ log.info("Verf\xFCgbare Optionen: --summary, --branch");
7000
+ return;
7001
+ }
7002
+ const spinner = ora9("Aktualisiere Session...").start();
7003
+ try {
7004
+ const result = await api2.updateSession(sessionId, {
7005
+ summary: options.summary,
7006
+ gitBranch: options.branch
7007
+ });
7008
+ if (result.success) {
7009
+ spinner.succeed("Session aktualisiert");
7010
+ } else {
7011
+ spinner.fail(result.message || "Fehler beim Aktualisieren");
7012
+ }
7013
+ } catch (error) {
7014
+ spinner.fail("Fehler beim Aktualisieren");
7015
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
7016
+ }
7017
+ });
6956
7018
 
6957
7019
  // src/commands/session/session.ts
6958
7020
  import { Command as Command14 } from "commander";
@@ -10389,67 +10451,6 @@ import inquirer8 from "inquirer";
10389
10451
  import ora13 from "ora";
10390
10452
  import * as fs6 from "fs";
10391
10453
  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
10454
  var SECURE_FILE_MODE = 384;
10454
10455
  var secretsCommand = new Command20("secrets").description("API Keys und Secrets verwalten (Cloud Vault)").action(async () => {
10455
10456
  await listSecrets();
@@ -11802,7 +11803,8 @@ function getColorFunction(color) {
11802
11803
  case "yellow":
11803
11804
  return colors.yellow;
11804
11805
  case "magenta":
11805
- return colors.magenta;
11806
+ return colors.cyan;
11807
+ // magenta not available, use cyan
11806
11808
  case "cyan":
11807
11809
  return colors.cyan;
11808
11810
  default:
@@ -11830,6 +11832,40 @@ async function resolveSessionId(input) {
11830
11832
  }
11831
11833
  return null;
11832
11834
  }
11835
+ tagsCommand.command("cloud").description("Memory-Tags aus Cloud laden").option("--json", "JSON Output").action(async (options) => {
11836
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
11837
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
11838
+ if (!isAuthenticated2()) {
11839
+ log.error("Nicht angemeldet");
11840
+ log.info("Anmelden mit: shiva login");
11841
+ return;
11842
+ }
11843
+ const ora24 = (await import("ora")).default;
11844
+ const spinner = ora24("Lade Memory-Tags aus Cloud...").start();
11845
+ try {
11846
+ const cloudTags = await api2.getMemoryTags();
11847
+ spinner.stop();
11848
+ if (options.json) {
11849
+ console.log(JSON.stringify(cloudTags, null, 2));
11850
+ return;
11851
+ }
11852
+ log.newline();
11853
+ console.log(colors.orange.bold("Memory Tags (Cloud)"));
11854
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
11855
+ log.newline();
11856
+ if (cloudTags.length === 0) {
11857
+ log.dim("Keine Memory-Tags in Cloud");
11858
+ return;
11859
+ }
11860
+ for (const { tag, count } of cloudTags) {
11861
+ console.log(` ${colors.cyan(`[${tag}]`)} ${colors.dim(`(${count} Memories)`)}`);
11862
+ }
11863
+ log.newline();
11864
+ } catch (error) {
11865
+ spinner.fail("Fehler beim Laden");
11866
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
11867
+ }
11868
+ });
11833
11869
 
11834
11870
  // src/commands/memory/export.ts
11835
11871
  import { Command as Command25 } from "commander";
@@ -11841,7 +11877,7 @@ import inquirer11 from "inquirer";
11841
11877
  // src/services/session/export.ts
11842
11878
  import * as fs9 from "fs";
11843
11879
  import * as path10 from "path";
11844
- import { execSync as execSync3 } from "child_process";
11880
+ import { execSync as execSync2 } from "child_process";
11845
11881
  async function exportSession(sessionId, options = {}) {
11846
11882
  const projects = await getAllClaudeProjects();
11847
11883
  for (const project of projects) {
@@ -11953,7 +11989,7 @@ function createBackupArchive(outputPath, projectPaths) {
11953
11989
  return false;
11954
11990
  }
11955
11991
  const tarArgs = includePaths.join(" ");
11956
- execSync3(`tar -czf "${outputPath}" -C "${claudeDir}" ${tarArgs}`, {
11992
+ execSync2(`tar -czf "${outputPath}" -C "${claudeDir}" ${tarArgs}`, {
11957
11993
  stdio: "ignore"
11958
11994
  });
11959
11995
  return true;
@@ -12061,7 +12097,7 @@ function restoreFromArchive(archivePath, targetDir) {
12061
12097
  if (!fs9.existsSync(extractTo)) {
12062
12098
  fs9.mkdirSync(extractTo, { recursive: true });
12063
12099
  }
12064
- execSync3(`tar -xzf "${archivePath}" -C "${extractTo}"`, {
12100
+ execSync2(`tar -xzf "${archivePath}" -C "${extractTo}"`, {
12065
12101
  stdio: "ignore"
12066
12102
  });
12067
12103
  return true;
@@ -12340,20 +12376,20 @@ var rememberCommand = new Command26("remember").description("Memory in der Cloud
12340
12376
 
12341
12377
  // src/commands/system/doctor.ts
12342
12378
  import { Command as Command27 } from "commander";
12343
- import { execSync as execSync4 } from "child_process";
12379
+ import { execSync as execSync3 } from "child_process";
12344
12380
  import * as fs11 from "fs";
12345
12381
  import * as path12 from "path";
12346
12382
  import * as os5 from "os";
12347
12383
  function tryExec(command) {
12348
12384
  try {
12349
- return execSync4(command, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
12385
+ return execSync3(command, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
12350
12386
  } catch {
12351
12387
  return null;
12352
12388
  }
12353
12389
  }
12354
- function commandExists3(cmd) {
12390
+ function commandExists2(cmd) {
12355
12391
  try {
12356
- execSync4(`which ${cmd}`, { stdio: ["pipe", "pipe", "pipe"] });
12392
+ execSync3(`which ${cmd}`, { stdio: ["pipe", "pipe", "pipe"] });
12357
12393
  return true;
12358
12394
  } catch {
12359
12395
  return false;
@@ -12366,7 +12402,7 @@ function getVersion(cmd, versionFlag = "--version") {
12366
12402
  return match ? match[0] : output.split("\n")[0];
12367
12403
  }
12368
12404
  function checkClaude() {
12369
- const exists = commandExists3("claude");
12405
+ const exists = commandExists2("claude");
12370
12406
  if (!exists) {
12371
12407
  return {
12372
12408
  name: "Claude CLI",
@@ -12383,7 +12419,7 @@ function checkClaude() {
12383
12419
  };
12384
12420
  }
12385
12421
  function checkGitHub() {
12386
- const exists = commandExists3("gh");
12422
+ const exists = commandExists2("gh");
12387
12423
  if (!exists) {
12388
12424
  return {
12389
12425
  name: "GitHub CLI (gh)",
@@ -12404,7 +12440,7 @@ function checkGitHub() {
12404
12440
  };
12405
12441
  }
12406
12442
  function checkDocker() {
12407
- const dockerExists = commandExists3("docker");
12443
+ const dockerExists = commandExists2("docker");
12408
12444
  if (dockerExists) {
12409
12445
  const version = getVersion("docker");
12410
12446
  const isRunning = tryExec("docker info 2>/dev/null") !== null;
@@ -12416,7 +12452,7 @@ function checkDocker() {
12416
12452
  hint: isRunning ? void 0 : "Starte Docker Desktop oder: sudo systemctl start docker"
12417
12453
  };
12418
12454
  }
12419
- const podmanExists = commandExists3("podman");
12455
+ const podmanExists = commandExists2("podman");
12420
12456
  if (podmanExists) {
12421
12457
  const version = getVersion("podman");
12422
12458
  return {
@@ -12433,7 +12469,7 @@ function checkDocker() {
12433
12469
  };
12434
12470
  }
12435
12471
  function checkGit() {
12436
- const exists = commandExists3("git");
12472
+ const exists = commandExists2("git");
12437
12473
  if (!exists) {
12438
12474
  return {
12439
12475
  name: "Git",
@@ -12461,7 +12497,7 @@ function checkGit() {
12461
12497
  };
12462
12498
  }
12463
12499
  function checkNode() {
12464
- const exists = commandExists3("node");
12500
+ const exists = commandExists2("node");
12465
12501
  if (!exists) {
12466
12502
  return {
12467
12503
  name: "Node.js",
@@ -12488,7 +12524,7 @@ function checkNode() {
12488
12524
  };
12489
12525
  }
12490
12526
  function checkNpm() {
12491
- const exists = commandExists3("npm");
12527
+ const exists = commandExists2("npm");
12492
12528
  if (!exists) {
12493
12529
  return {
12494
12530
  name: "npm",
@@ -12556,7 +12592,7 @@ function checkClaudeProjects() {
12556
12592
  }
12557
12593
  }
12558
12594
  function checkTmux() {
12559
- const exists = commandExists3("tmux");
12595
+ const exists = commandExists2("tmux");
12560
12596
  if (!exists) {
12561
12597
  return {
12562
12598
  name: "tmux",
@@ -12667,7 +12703,7 @@ var doctorCommand = new Command27("doctor").description("System-Check f\xFCr SHI
12667
12703
 
12668
12704
  // src/commands/system/upgrade.ts
12669
12705
  import { Command as Command28 } from "commander";
12670
- import { execSync as execSync5, spawn as spawn6 } from "child_process";
12706
+ import { execSync as execSync4, spawn as spawn6 } from "child_process";
12671
12707
  import * as fs12 from "fs";
12672
12708
  import * as path13 from "path";
12673
12709
  import { fileURLToPath } from "url";
@@ -12693,7 +12729,7 @@ async function getLatestVersion() {
12693
12729
  return data["dist-tags"]?.latest || null;
12694
12730
  } catch {
12695
12731
  try {
12696
- const output = execSync5(`npm view ${PACKAGE_NAME} version 2>/dev/null`, {
12732
+ const output = execSync4(`npm view ${PACKAGE_NAME} version 2>/dev/null`, {
12697
12733
  encoding: "utf-8"
12698
12734
  }).trim();
12699
12735
  return output || null;
@@ -12724,17 +12760,17 @@ async function checkForUpdates() {
12724
12760
  }
12725
12761
  function detectPackageManager2() {
12726
12762
  try {
12727
- const npmGlobal = execSync5("npm list -g --depth=0 2>/dev/null", { encoding: "utf-8" });
12763
+ const npmGlobal = execSync4("npm list -g --depth=0 2>/dev/null", { encoding: "utf-8" });
12728
12764
  if (npmGlobal.includes(PACKAGE_NAME)) return "npm";
12729
12765
  } catch {
12730
12766
  }
12731
12767
  try {
12732
- const yarnGlobal = execSync5("yarn global list 2>/dev/null", { encoding: "utf-8" });
12768
+ const yarnGlobal = execSync4("yarn global list 2>/dev/null", { encoding: "utf-8" });
12733
12769
  if (yarnGlobal.includes(PACKAGE_NAME)) return "yarn";
12734
12770
  } catch {
12735
12771
  }
12736
12772
  try {
12737
- const pnpmGlobal = execSync5("pnpm list -g 2>/dev/null", { encoding: "utf-8" });
12773
+ const pnpmGlobal = execSync4("pnpm list -g 2>/dev/null", { encoding: "utf-8" });
12738
12774
  if (pnpmGlobal.includes(PACKAGE_NAME)) return "pnpm";
12739
12775
  } catch {
12740
12776
  }
@@ -13499,29 +13535,508 @@ function formatNumber(n) {
13499
13535
  }
13500
13536
  return String(n);
13501
13537
  }
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");
13538
+ statsCommand.command("sessions").description("Session Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
13539
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
13540
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
13541
+ if (!isAuthenticated2()) {
13542
+ log.error("Nicht angemeldet");
13543
+ log.info("Anmelden mit: shiva login");
13544
+ return;
13545
+ }
13546
+ const spinner = ora18("Lade Session Analytics...").start();
13547
+ try {
13548
+ const analytics = await api2.getSessionAnalytics();
13549
+ spinner.stop();
13550
+ if (options.json) {
13551
+ console.log(JSON.stringify(analytics, null, 2));
13552
+ return;
13553
+ }
13554
+ log.newline();
13555
+ console.log(colors.orange.bold("Session Analytics"));
13556
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13557
+ log.newline();
13558
+ log.keyValue("Avg Session Length", `${analytics.averageSessionLength} min`);
13559
+ log.newline();
13560
+ console.log(colors.bold("Peak Hours:"));
13561
+ const sortedHours = analytics.peakHours.sort((a, b) => b.count - a.count).slice(0, 5);
13562
+ for (const { hour, count } of sortedHours) {
13563
+ console.log(` ${String(hour).padStart(2)}:00 - ${count} sessions`);
13564
+ }
13565
+ log.newline();
13566
+ console.log(colors.bold("Top Projects by Sessions:"));
13567
+ for (const proj of analytics.topProjects.slice(0, 5)) {
13568
+ console.log(` ${proj.projectName.padEnd(25)} ${proj.sessionCount} sessions`);
13569
+ }
13570
+ log.newline();
13571
+ if (analytics.dailySessions.length > 0) {
13572
+ console.log(colors.bold("Sessions (Last 7 Days):"));
13573
+ for (const { date, count } of analytics.dailySessions.slice(-7)) {
13574
+ const barLength = Math.min(20, count);
13575
+ const bar = colors.green("\u2588".repeat(barLength));
13576
+ console.log(` ${date.slice(5)} ${bar} ${count}`);
13577
+ }
13578
+ }
13579
+ } catch (error) {
13580
+ spinner.fail("Fehler beim Laden");
13581
+ const err = error;
13582
+ if (err.message?.includes("403") || err.message?.includes("forbidden")) {
13583
+ log.warn("Session Analytics ist ein Pro-Feature");
13584
+ log.info("Upgrade auf Pro: https://shiva.li/pricing");
13585
+ } else {
13586
+ log.error(err.message || "Unbekannter Fehler");
13587
+ }
13588
+ }
13589
+ });
13590
+ statsCommand.command("tokens").description("Token Usage Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
13591
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
13592
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
13593
+ if (!isAuthenticated2()) {
13594
+ log.error("Nicht angemeldet");
13595
+ log.info("Anmelden mit: shiva login");
13596
+ return;
13597
+ }
13598
+ const spinner = ora18("Lade Token Analytics...").start();
13599
+ try {
13600
+ const analytics = await api2.getTokenAnalytics();
13601
+ spinner.stop();
13602
+ if (options.json) {
13603
+ console.log(JSON.stringify(analytics, null, 2));
13604
+ return;
13605
+ }
13606
+ log.newline();
13607
+ console.log(colors.orange.bold("Token Usage Analytics"));
13608
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13609
+ log.newline();
13610
+ log.keyValue("Total Tokens", formatNumber(analytics.totalTokens));
13611
+ log.keyValue("This Month", formatNumber(analytics.tokensThisMonth));
13612
+ log.newline();
13613
+ console.log(colors.bold("Token Usage by Project:"));
13614
+ for (const proj of analytics.byProject.slice(0, 5)) {
13615
+ console.log(` ${proj.projectName.padEnd(25)} ${formatNumber(proj.tokens)}`);
13616
+ }
13617
+ log.newline();
13618
+ if (analytics.dailyUsage.length > 0) {
13619
+ console.log(colors.bold("Daily Usage (Last 7 Days):"));
13620
+ const maxTokens = Math.max(...analytics.dailyUsage.slice(-7).map((d) => d.tokens), 1);
13621
+ for (const { date, tokens } of analytics.dailyUsage.slice(-7)) {
13622
+ const barLength = Math.round(tokens / maxTokens * 20);
13623
+ const bar = colors.cyan("\u2588".repeat(barLength)) + colors.dim("\u2591".repeat(20 - barLength));
13624
+ console.log(` ${date.slice(5)} ${bar} ${formatNumber(tokens)}`);
13625
+ }
13626
+ }
13627
+ } catch (error) {
13628
+ spinner.fail("Fehler beim Laden");
13629
+ const err = error;
13630
+ if (err.message?.includes("403") || err.message?.includes("forbidden")) {
13631
+ log.warn("Token Analytics ist ein Pro-Feature");
13632
+ log.info("Upgrade auf Pro: https://shiva.li/pricing");
13633
+ } else {
13634
+ log.error(err.message || "Unbekannter Fehler");
13635
+ }
13636
+ }
13637
+ });
13638
+ statsCommand.command("tools").description("Tool Usage Analytics (Pro Feature)").option("--json", "JSON Output").action(async (options) => {
13639
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
13640
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
13641
+ if (!isAuthenticated2()) {
13642
+ log.error("Nicht angemeldet");
13643
+ log.info("Anmelden mit: shiva login");
13644
+ return;
13645
+ }
13646
+ const spinner = ora18("Lade Tool Analytics...").start();
13647
+ try {
13648
+ const analytics = await api2.getToolAnalytics();
13649
+ spinner.stop();
13650
+ if (options.json) {
13651
+ console.log(JSON.stringify(analytics, null, 2));
13652
+ return;
13653
+ }
13654
+ log.newline();
13655
+ console.log(colors.orange.bold("Tool Usage Analytics"));
13656
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13657
+ log.newline();
13658
+ log.keyValue("Total Tool Calls", formatNumber(analytics.totalToolCalls));
13659
+ log.newline();
13660
+ console.log(colors.bold("Most Used Tools:"));
13661
+ for (const tool of analytics.mostUsedTools.slice(0, 10)) {
13662
+ const bar = colors.yellow("\u2588".repeat(Math.min(20, Math.round(tool.count / 10))));
13663
+ console.log(` ${tool.tool.padEnd(20)} ${bar} ${formatNumber(tool.count)}`);
13664
+ }
13665
+ log.newline();
13666
+ console.log(colors.bold("Tool Performance (Avg Duration):"));
13667
+ const sorted = analytics.byTool.sort((a, b) => b.avgDuration - a.avgDuration).slice(0, 5);
13668
+ for (const tool of sorted) {
13669
+ console.log(` ${tool.tool.padEnd(20)} ${tool.avgDuration.toFixed(0)}ms`);
13670
+ }
13671
+ } catch (error) {
13672
+ spinner.fail("Fehler beim Laden");
13673
+ const err = error;
13674
+ if (err.message?.includes("403") || err.message?.includes("forbidden")) {
13675
+ log.warn("Tool Analytics ist ein Pro-Feature");
13676
+ log.info("Upgrade auf Pro: https://shiva.li/pricing");
13677
+ } else {
13678
+ log.error(err.message || "Unbekannter Fehler");
13679
+ }
13680
+ }
13681
+ });
13682
+ 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) => {
13683
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
13684
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
13685
+ const { writeFileSync: writeFileSync11 } = await import("fs");
13686
+ if (!isAuthenticated2()) {
13687
+ log.error("Nicht angemeldet");
13688
+ log.info("Anmelden mit: shiva login");
13689
+ return;
13690
+ }
13691
+ const spinner = ora18("Exportiere Analytics...").start();
13692
+ try {
13693
+ const result = await api2.exportAnalytics({
13694
+ startDate: options.start,
13695
+ endDate: options.end,
13696
+ format: options.format
13697
+ });
13698
+ spinner.stop();
13699
+ if (options.output) {
13700
+ const content = options.format === "json" ? JSON.stringify(result.data, null, 2) : String(result.data);
13701
+ writeFileSync11(options.output, content);
13702
+ log.success(`Analytics exportiert: ${options.output}`);
13703
+ } else {
13704
+ console.log(JSON.stringify(result, null, 2));
13705
+ }
13706
+ } catch (error) {
13707
+ spinner.fail("Fehler beim Exportieren");
13708
+ const err = error;
13709
+ if (err.message?.includes("403") || err.message?.includes("forbidden")) {
13710
+ log.warn("Analytics Export ist ein Pro-Feature");
13711
+ log.info("Upgrade auf Pro: https://shiva.li/pricing");
13712
+ } else {
13713
+ log.error(err.message || "Unbekannter Fehler");
13714
+ }
13715
+ }
13716
+ });
13717
+ statsCommand.command("track").description("Analytics Event tracken").argument("<type>", "Event-Typ").argument("[data]", "Event-Daten als JSON").action(async (type2, data) => {
13718
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
13719
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
13720
+ if (!isAuthenticated2()) {
13721
+ log.error("Nicht angemeldet");
13722
+ log.info("Anmelden mit: shiva login");
13723
+ return;
13724
+ }
13725
+ try {
13726
+ const eventData = data ? JSON.parse(data) : {};
13727
+ const result = await api2.trackAnalyticsEvent({
13728
+ type: type2,
13729
+ data: eventData
13730
+ });
13731
+ if (result.success) {
13732
+ log.success("Event getrackt");
13733
+ } else {
13734
+ log.error("Event konnte nicht getrackt werden");
13735
+ }
13736
+ } catch (error) {
13737
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13738
+ }
13739
+ });
13740
+
13741
+ // src/commands/system/user.ts
13742
+ import { Command as Command32 } from "commander";
13743
+ import ora19 from "ora";
13744
+ var userCommand = new Command32("user").description("User Account Verwaltung");
13745
+ userCommand.command("profile").description("User-Profil anzeigen").option("--json", "JSON Output").action(async (options) => {
13746
+ if (!isAuthenticated()) {
13747
+ log.error("Nicht angemeldet");
13748
+ log.info("Anmelden mit: shiva login");
13749
+ return;
13750
+ }
13751
+ const spinner = ora19("Lade Profil...").start();
13752
+ try {
13753
+ const profile = await api.getUserProfile();
13754
+ spinner.stop();
13755
+ if (options.json) {
13756
+ console.log(JSON.stringify(profile, null, 2));
13757
+ return;
13758
+ }
13759
+ log.newline();
13760
+ console.log(colors.orange.bold("User Profile"));
13761
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13762
+ log.newline();
13763
+ log.keyValue("ID", String(profile.id));
13764
+ log.keyValue("Email", profile.email);
13765
+ if (profile.name) {
13766
+ log.keyValue("Name", profile.name);
13767
+ }
13768
+ const tierColor = profile.tier === "pro" ? colors.cyan : profile.tier === "team" ? colors.green : colors.dim;
13769
+ log.keyValue("Tier", tierColor(profile.tier.toUpperCase()));
13770
+ log.keyValue("Seit", new Date(profile.createdAt).toLocaleDateString("de-DE"));
13771
+ } catch (error) {
13772
+ spinner.fail("Fehler beim Laden");
13773
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13774
+ }
13775
+ });
13776
+ userCommand.command("update").description("User-Profil aktualisieren").option("--name <name>", "Name setzen").action(async (options) => {
13777
+ if (!isAuthenticated()) {
13778
+ log.error("Nicht angemeldet");
13779
+ log.info("Anmelden mit: shiva login");
13780
+ return;
13781
+ }
13782
+ if (!options.name) {
13783
+ log.error("Keine \xC4nderungen angegeben");
13784
+ log.info("Verf\xFCgbare Optionen:");
13785
+ log.plain(" --name <name> Name setzen");
13786
+ return;
13787
+ }
13788
+ const spinner = ora19("Aktualisiere Profil...").start();
13789
+ try {
13790
+ const result = await api.updateUserProfile({
13791
+ name: options.name
13792
+ });
13793
+ if (result.success) {
13794
+ spinner.succeed("Profil aktualisiert");
13795
+ } else {
13796
+ spinner.fail(result.message || "Fehler beim Aktualisieren");
13797
+ }
13798
+ } catch (error) {
13799
+ spinner.fail("Fehler beim Aktualisieren");
13800
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13801
+ }
13802
+ });
13803
+ userCommand.command("usage").description("Resource-Nutzung und Limits anzeigen").option("--json", "JSON Output").action(async (options) => {
13804
+ if (!isAuthenticated()) {
13805
+ log.error("Nicht angemeldet");
13806
+ log.info("Anmelden mit: shiva login");
13807
+ return;
13808
+ }
13809
+ const spinner = ora19("Lade Usage...").start();
13810
+ try {
13811
+ const usage = await api.getUserUsage();
13812
+ spinner.stop();
13813
+ if (options.json) {
13814
+ console.log(JSON.stringify(usage, null, 2));
13815
+ return;
13816
+ }
13817
+ log.newline();
13818
+ console.log(colors.orange.bold("Resource Usage"));
13819
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13820
+ log.newline();
13821
+ const progressBar = (current, limit, label, unit) => {
13822
+ const percentage = Math.min(100, Math.round(current / limit * 100));
13823
+ const barWidth = 20;
13824
+ const filled = Math.round(current / limit * barWidth);
13825
+ const empty = barWidth - filled;
13826
+ const barColor = percentage >= 90 ? colors.red : percentage >= 70 ? colors.yellow : colors.green;
13827
+ const bar = barColor("\u2588".repeat(filled)) + colors.dim("\u2591".repeat(empty));
13828
+ const unitStr = unit ? ` ${unit}` : "";
13829
+ console.log(` ${label.padEnd(12)} [${bar}] ${current}/${limit}${unitStr} (${percentage}%)`);
13830
+ };
13831
+ progressBar(usage.projects.current, usage.projects.limit, "Projects");
13832
+ progressBar(usage.sessions.current, usage.sessions.limit, "Sessions");
13833
+ progressBar(usage.storage.current, usage.storage.limit, "Storage", usage.storage.unit);
13834
+ progressBar(usage.apiCalls.current, usage.apiCalls.limit, "API Calls", `/${usage.apiCalls.period}`);
13835
+ log.newline();
13836
+ const nearLimit = (current, limit) => current / limit >= 0.9;
13837
+ 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)) {
13838
+ log.warn("Du erreichst bald deine Limits");
13839
+ log.info("Upgrade auf Pro: shiva user subscription");
13840
+ }
13841
+ } catch (error) {
13842
+ spinner.fail("Fehler beim Laden");
13843
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13844
+ }
13845
+ });
13846
+ userCommand.command("subscription").description("Subscription-Status anzeigen").option("--json", "JSON Output").action(async (options) => {
13847
+ if (!isAuthenticated()) {
13848
+ log.error("Nicht angemeldet");
13849
+ log.info("Anmelden mit: shiva login");
13850
+ return;
13851
+ }
13852
+ const spinner = ora19("Lade Subscription...").start();
13853
+ try {
13854
+ const sub = await api.getSubscription();
13855
+ spinner.stop();
13856
+ if (options.json) {
13857
+ console.log(JSON.stringify(sub, null, 2));
13858
+ return;
13859
+ }
13860
+ log.newline();
13861
+ console.log(colors.orange.bold("Subscription"));
13862
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
13863
+ log.newline();
13864
+ const tierColor = sub.tier === "pro" ? colors.cyan : sub.tier === "team" ? colors.green : colors.dim;
13865
+ log.keyValue("Tier", tierColor(sub.tier.toUpperCase()));
13866
+ const statusColor = sub.status === "active" ? colors.green : sub.status === "trialing" ? colors.yellow : colors.red;
13867
+ log.keyValue("Status", statusColor(sub.status));
13868
+ if (sub.billingCycle) {
13869
+ log.keyValue("Billing", sub.billingCycle);
13870
+ }
13871
+ if (sub.currentPeriodEnd) {
13872
+ const endDate = new Date(sub.currentPeriodEnd);
13873
+ const label = sub.cancelAtPeriodEnd ? "Endet am" : "Renewal";
13874
+ log.keyValue(label, endDate.toLocaleDateString("de-DE"));
13875
+ }
13876
+ if (sub.cancelAtPeriodEnd) {
13877
+ log.newline();
13878
+ log.warn("Subscription endet am Ende der aktuellen Periode");
13879
+ }
13880
+ log.newline();
13881
+ console.log(colors.bold("Features:"));
13882
+ for (const feature of sub.features) {
13883
+ console.log(` ${colors.green("\u2713")} ${feature}`);
13884
+ }
13885
+ if (sub.tier === "free") {
13886
+ log.newline();
13887
+ log.info("Upgrade auf Pro f\xFCr mehr Features:");
13888
+ log.plain(" https://shiva.li/pricing");
13889
+ }
13890
+ } catch (error) {
13891
+ spinner.fail("Fehler beim Laden");
13892
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13893
+ }
13894
+ });
13895
+ userCommand.command("token").description("Neuen CLI-Token generieren").option("--copy", "Token in Zwischenablage kopieren").action(async (options) => {
13896
+ if (!isAuthenticated()) {
13897
+ log.error("Nicht angemeldet");
13898
+ log.info("Anmelden mit: shiva login");
13899
+ return;
13900
+ }
13901
+ const { default: inquirer14 } = await import("inquirer");
13902
+ const { confirm } = await inquirer14.prompt([{
13903
+ type: "confirm",
13904
+ name: "confirm",
13905
+ message: "Neuen Token generieren? Der alte Token wird ung\xFCltig.",
13906
+ default: false
13907
+ }]);
13908
+ if (!confirm) {
13909
+ log.dim("Abgebrochen");
13910
+ return;
13911
+ }
13912
+ const spinner = ora19("Generiere Token...").start();
13913
+ try {
13914
+ const result = await api.generateCliToken();
13915
+ spinner.stop();
13916
+ log.newline();
13917
+ log.success("Token generiert");
13918
+ log.newline();
13919
+ log.warn("Dieser Token wird nur einmal angezeigt!");
13920
+ log.newline();
13921
+ console.log(colors.dim("Token:"));
13922
+ console.log(colors.cyan(result.token));
13923
+ log.newline();
13924
+ log.keyValue("G\xFCltig bis", new Date(result.expiresAt).toLocaleDateString("de-DE"));
13925
+ if (options.copy) {
13926
+ try {
13927
+ const { copyToClipboard: copyToClipboard2 } = await import("./clipboard-ET53HNUB.js");
13928
+ await copyToClipboard2(result.token);
13929
+ log.success("Token in Zwischenablage kopiert");
13930
+ } catch {
13931
+ log.dim("Konnte nicht in Zwischenablage kopieren");
13932
+ }
13933
+ }
13934
+ log.newline();
13935
+ log.info("Verwendung:");
13936
+ log.plain(` export SHIVA_TOKEN="${result.token}"`);
13937
+ log.plain(" # oder in ~/.bashrc / ~/.zshrc");
13938
+ } catch (error) {
13939
+ spinner.fail("Fehler beim Generieren");
13940
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13941
+ }
13942
+ });
13943
+ userCommand.command("delete").description("Account unwiderruflich l\xF6schen").action(async () => {
13944
+ if (!isAuthenticated()) {
13945
+ log.error("Nicht angemeldet");
13946
+ return;
13947
+ }
13948
+ log.newline();
13949
+ log.warn("ACHTUNG: Account l\xF6schen ist IRREVERSIBEL!");
13950
+ log.newline();
13951
+ log.plain("Folgende Daten werden unwiderruflich gel\xF6scht:");
13952
+ log.plain(" \u2022 Alle Projekte und Memories");
13953
+ log.plain(" \u2022 Alle Sessions und Sandboxes");
13954
+ log.plain(" \u2022 Alle Secrets und Einstellungen");
13955
+ log.plain(" \u2022 Subscription und Zahlungsdaten");
13956
+ log.newline();
13957
+ const { default: inquirer14 } = await import("inquirer");
13958
+ const { confirm1 } = await inquirer14.prompt([{
13959
+ type: "confirm",
13960
+ name: "confirm1",
13961
+ message: "Bist du sicher, dass du deinen Account l\xF6schen m\xF6chtest?",
13962
+ default: false
13963
+ }]);
13964
+ if (!confirm1) {
13965
+ log.dim("Abgebrochen");
13966
+ return;
13967
+ }
13968
+ const { confirmText } = await inquirer14.prompt([{
13969
+ type: "input",
13970
+ name: "confirmText",
13971
+ message: 'Tippe "DELETE" um zu best\xE4tigen:'
13972
+ }]);
13973
+ if (confirmText !== "DELETE") {
13974
+ log.dim("Abgebrochen (falscher Best\xE4tigungstext)");
13975
+ return;
13976
+ }
13977
+ const spinner = ora19("L\xF6sche Account...").start();
13978
+ try {
13979
+ const result = await api.deleteAccount("DELETE");
13980
+ if (result.success) {
13981
+ spinner.succeed("Account gel\xF6scht");
13982
+ log.newline();
13983
+ clearAuth();
13984
+ log.info("Lokale Anmeldedaten wurden entfernt");
13985
+ log.plain("Auf Wiedersehen!");
13986
+ } else {
13987
+ spinner.fail(result.message || "Fehler beim L\xF6schen");
13988
+ }
13989
+ } catch (error) {
13990
+ spinner.fail("Fehler beim L\xF6schen");
13991
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
13992
+ }
13993
+ });
13994
+ userCommand.command("whoami").description("Aktuelle Anmeldung anzeigen").action(async () => {
13995
+ const config = getConfig();
13996
+ if (!isAuthenticated()) {
13997
+ log.info("Nicht angemeldet");
13998
+ log.plain("Anmelden mit: shiva login");
13999
+ return;
14000
+ }
14001
+ log.newline();
14002
+ log.keyValue("Email", config.email || "Unbekannt");
14003
+ log.keyValue("Tier", config.tier || "Unbekannt");
14004
+ log.keyValue("User ID", String(config.userId) || "Unbekannt");
14005
+ if (config.tokenExpiry) {
14006
+ const expiry = new Date(config.tokenExpiry);
14007
+ const now = /* @__PURE__ */ new Date();
14008
+ const daysLeft = Math.ceil((expiry.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
14009
+ if (daysLeft > 0) {
14010
+ log.keyValue("Token g\xFCltig", `${daysLeft} Tage`);
14011
+ } else {
14012
+ log.warn("Token abgelaufen");
14013
+ log.info("Neu anmelden mit: shiva login");
14014
+ }
14015
+ }
14016
+ });
14017
+
14018
+ // src/commands/advanced/docker.ts
14019
+ import { Command as Command33 } from "commander";
14020
+ import ora20 from "ora";
14021
+ var dockerCommand = new Command33("docker").description("Docker-Integration verwalten");
14022
+ dockerCommand.command("status").description("Docker-Verf\xFCgbarkeit pr\xFCfen").action(() => {
14023
+ log.brand();
14024
+ log.header("Docker Status");
14025
+ log.newline();
14026
+ const info = dockerService.getDockerInfo();
14027
+ const settings = settingsSync.getDockerSettings();
14028
+ if (info.available) {
14029
+ log.keyValue("Runtime", `${info.runtime === "podman" ? "Podman" : "Docker"} ${info.version}`);
14030
+ log.keyValue("Socket", info.socket || colors.dim("default"));
14031
+ log.keyValue("Status", colors.green("Verf\xFCgbar"));
14032
+ } else {
14033
+ log.keyValue("Runtime", colors.dim("nicht gefunden"));
14034
+ log.keyValue("Status", colors.red("Nicht verf\xFCgbar"));
14035
+ log.newline();
14036
+ log.warn("Docker oder Podman ist nicht installiert");
14037
+ log.dim("Installation:");
14038
+ log.dim(" Docker: https://docs.docker.com/get-docker/");
14039
+ log.dim(" Podman: https://podman.io/get-started");
13525
14040
  return;
13526
14041
  }
13527
14042
  log.newline();
@@ -13568,7 +14083,7 @@ dockerCommand.command("enable").description("Docker-Modus aktivieren").action(as
13568
14083
  return;
13569
14084
  }
13570
14085
  const image = dockerService.getDefaultImage();
13571
- const spinner = ora19(`Pr\xFCfe Image: ${image}...`).start();
14086
+ const spinner = ora20(`Pr\xFCfe Image: ${image}...`).start();
13572
14087
  if (!dockerService.imageExists(image)) {
13573
14088
  spinner.text = `Lade Image herunter: ${image}...`;
13574
14089
  try {
@@ -13627,7 +14142,7 @@ dockerCommand.command("logs").description("Container-Logs anzeigen").argument("<
13627
14142
  console.log(logs);
13628
14143
  });
13629
14144
  dockerCommand.command("stop").description("Container stoppen").argument("<name>", "Container-Name oder ID").action(async (name) => {
13630
- const spinner = ora19(`Stoppe Container ${name}...`).start();
14145
+ const spinner = ora20(`Stoppe Container ${name}...`).start();
13631
14146
  try {
13632
14147
  await dockerService.stopContainer(name);
13633
14148
  spinner.succeed(`Container gestoppt: ${name}`);
@@ -13637,7 +14152,7 @@ dockerCommand.command("stop").description("Container stoppen").argument("<name>"
13637
14152
  }
13638
14153
  });
13639
14154
  dockerCommand.command("clean").description("Gestoppte Container aufr\xE4umen").action(async () => {
13640
- const spinner = ora19("R\xE4ume Container auf...").start();
14155
+ const spinner = ora20("R\xE4ume Container auf...").start();
13641
14156
  try {
13642
14157
  const count = await dockerService.cleanContainers();
13643
14158
  spinner.succeed(`${count} Container entfernt`);
@@ -13648,7 +14163,7 @@ dockerCommand.command("clean").description("Gestoppte Container aufr\xE4umen").a
13648
14163
  });
13649
14164
  dockerCommand.command("pull").description("Docker-Image herunterladen").argument("[image]", "Image-Name (default: shiva/claude-runner:latest)").action(async (image) => {
13650
14165
  const targetImage = image || dockerService.getDefaultImage();
13651
- const spinner = ora19(`Lade Image herunter: ${targetImage}...`).start();
14166
+ const spinner = ora20(`Lade Image herunter: ${targetImage}...`).start();
13652
14167
  try {
13653
14168
  await dockerService.pullImage(targetImage);
13654
14169
  spinner.succeed(`Image heruntergeladen: ${targetImage}`);
@@ -13733,11 +14248,11 @@ dockerCommand.action(() => {
13733
14248
  });
13734
14249
 
13735
14250
  // src/commands/advanced/workflow.ts
13736
- import { Command as Command33 } from "commander";
14251
+ import { Command as Command34 } from "commander";
13737
14252
  import * as fs13 from "fs";
13738
14253
  import * as path14 from "path";
13739
14254
  import * as os6 from "os";
13740
- import ora20 from "ora";
14255
+ import ora21 from "ora";
13741
14256
  import inquirer12 from "inquirer";
13742
14257
  var builtInWorkflows = {
13743
14258
  morning: {
@@ -13757,7 +14272,7 @@ var builtInWorkflows = {
13757
14272
  ]
13758
14273
  }
13759
14274
  };
13760
- var workflowCommand = new Command33("workflow").description("Automatisierte Workflows ausf\xFChren").action(async () => {
14275
+ var workflowCommand = new Command34("workflow").description("Automatisierte Workflows ausf\xFChren").action(async () => {
13761
14276
  await listWorkflows();
13762
14277
  });
13763
14278
  workflowCommand.command("list").alias("ls").description("Verf\xFCgbare Workflows anzeigen").action(async () => {
@@ -13926,7 +14441,7 @@ function deleteCustomWorkflow(name) {
13926
14441
  fs13.writeFileSync(filepath, JSON.stringify(workflows, null, 2));
13927
14442
  }
13928
14443
  async function executeStep(step) {
13929
- const spinner = ora20("Ausf\xFChren...").start();
14444
+ const spinner = ora21("Ausf\xFChren...").start();
13930
14445
  try {
13931
14446
  switch (step.type) {
13932
14447
  case "issues": {
@@ -14012,7 +14527,7 @@ async function executeStep(step) {
14012
14527
  }
14013
14528
 
14014
14529
  // src/commands/advanced/hook.ts
14015
- import { Command as Command34 } from "commander";
14530
+ import { Command as Command35 } from "commander";
14016
14531
  import { existsSync as existsSync21, readFileSync as readFileSync10, writeFileSync as writeFileSync10, mkdirSync as mkdirSync6 } from "fs";
14017
14532
  import { homedir as homedir7 } from "os";
14018
14533
  import { join as join12 } from "path";
@@ -14047,7 +14562,7 @@ function removeShivaHooks(eventHooks) {
14047
14562
  (entry) => !entry.hooks?.some((h) => h.command?.includes("shiva"))
14048
14563
  );
14049
14564
  }
14050
- var hookCommand = new Command34("hook").description("Claude Code Hook Integration verwalten");
14565
+ var hookCommand = new Command35("hook").description("Claude Code Hook Integration verwalten");
14051
14566
  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
14567
  log.brand();
14053
14568
  const claudePath = join12(homedir7(), ".claude");
@@ -14382,7 +14897,7 @@ hookCommand.command("scan-command").description("Scanne Bash-Befehle auf Package
14382
14897
  }
14383
14898
  });
14384
14899
  hookCommand.command("push").description("Hooks in Cloud sichern").action(async () => {
14385
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
14900
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14386
14901
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14387
14902
  if (!isAuthenticated2()) {
14388
14903
  log.error("Nicht angemeldet");
@@ -14395,78 +14910,252 @@ hookCommand.command("push").description("Hooks in Cloud sichern").action(async (
14395
14910
  return;
14396
14911
  }
14397
14912
  try {
14398
- await api2.updateHooks(settings.hooks);
14399
- log.success("Hooks in Cloud gesichert");
14913
+ await api2.updateHooks(settings.hooks);
14914
+ log.success("Hooks in Cloud gesichert");
14915
+ } catch (error) {
14916
+ log.error(error instanceof Error ? error.message : "Fehler beim Sichern");
14917
+ }
14918
+ });
14919
+ hookCommand.command("pull").description("Hooks aus Cloud laden").option("-f, --force", "Lokale Hooks \xFCberschreiben").action(async (options) => {
14920
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14921
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14922
+ if (!isAuthenticated2()) {
14923
+ log.error("Nicht angemeldet");
14924
+ log.info("Anmelden mit: shiva login");
14925
+ return;
14926
+ }
14927
+ const settings = getClaudeSettings();
14928
+ if (settings.hooks && !options.force) {
14929
+ log.warn("Lokale Hooks existieren bereits");
14930
+ log.info("Mit --force \xFCberschreiben");
14931
+ return;
14932
+ }
14933
+ try {
14934
+ const result = await api2.getHooks();
14935
+ if (!result.hooks || Object.keys(result.hooks).length === 0) {
14936
+ log.info("Keine Hooks in Cloud gefunden");
14937
+ return;
14938
+ }
14939
+ settings.hooks = result.hooks;
14940
+ saveClaudeSettings(settings);
14941
+ log.success("Hooks aus Cloud geladen");
14942
+ log.newline();
14943
+ log.info("Aktive Hooks:");
14944
+ for (const [event, hooks] of Object.entries(result.hooks)) {
14945
+ log.tree.item(`${event}: ${Array.isArray(hooks) ? hooks.length : 1} Hook(s)`);
14946
+ }
14947
+ } catch (error) {
14948
+ log.error(error instanceof Error ? error.message : "Fehler beim Laden");
14949
+ }
14950
+ });
14951
+ hookCommand.command("sync").description("Hooks mit Cloud synchronisieren").action(async () => {
14952
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14953
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14954
+ if (!isAuthenticated2()) {
14955
+ log.error("Nicht angemeldet");
14956
+ log.info("Anmelden mit: shiva login");
14957
+ return;
14958
+ }
14959
+ const settings = getClaudeSettings();
14960
+ try {
14961
+ if (settings.hooks) {
14962
+ await api2.updateHooks(settings.hooks);
14963
+ log.success("Lokale Hooks \u2192 Cloud");
14964
+ }
14965
+ const result = await api2.getHooks();
14966
+ if (result.hooks && Object.keys(result.hooks).length > 0) {
14967
+ const merged = { ...result.hooks, ...settings.hooks };
14968
+ settings.hooks = merged;
14969
+ saveClaudeSettings(settings);
14970
+ log.success("Cloud Hooks \u2192 Lokal (merged)");
14971
+ }
14972
+ log.newline();
14973
+ log.success("Hooks synchronisiert");
14974
+ } catch (error) {
14975
+ log.error(error instanceof Error ? error.message : "Fehler beim Synchronisieren");
14976
+ }
14977
+ });
14978
+ hookCommand.command("cloud-list").description("Cloud-Hooks auflisten").option("--event <type>", "Nach Event-Typ filtern").option("--json", "JSON Output").action(async (options) => {
14979
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14980
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14981
+ const { colors: colors3 } = await import("./logger-E7SC5KUO.js");
14982
+ if (!isAuthenticated2()) {
14983
+ log.error("Nicht angemeldet");
14984
+ log.info("Anmelden mit: shiva login");
14985
+ return;
14986
+ }
14987
+ const ora24 = (await import("ora")).default;
14988
+ const spinner = ora24("Lade Cloud-Hooks...").start();
14989
+ try {
14990
+ let hooks;
14991
+ if (options.event) {
14992
+ hooks = await api2.getHooksForEvent(options.event);
14993
+ } else {
14994
+ const result = await api2.getHooks();
14995
+ hooks = result.hooks || [];
14996
+ }
14997
+ spinner.stop();
14998
+ if (options.json) {
14999
+ console.log(JSON.stringify(hooks, null, 2));
15000
+ return;
15001
+ }
15002
+ log.newline();
15003
+ console.log(colors3.orange.bold("Cloud Hooks"));
15004
+ console.log(colors3.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
15005
+ log.newline();
15006
+ if (!hooks || Array.isArray(hooks) && hooks.length === 0) {
15007
+ log.dim("Keine Cloud-Hooks konfiguriert");
15008
+ return;
15009
+ }
15010
+ const hooksArray = Array.isArray(hooks) ? hooks : Object.values(hooks).flat();
15011
+ for (const hook of hooksArray) {
15012
+ const enabledIcon = hook.enabled !== false ? colors3.green("\u25CF") : colors3.dim("\u25CB");
15013
+ console.log(` ${enabledIcon} ${colors3.bold(hook.id || hook.event)}`);
15014
+ console.log(` ${colors3.dim("Event:")} ${hook.event}`);
15015
+ if (hook.matcher) {
15016
+ console.log(` ${colors3.dim("Matcher:")} ${hook.matcher}`);
15017
+ }
15018
+ console.log(` ${colors3.dim("Type:")} ${hook.type}`);
15019
+ console.log(` ${colors3.dim("Command:")} ${hook.command}`);
15020
+ log.newline();
15021
+ }
15022
+ } catch (error) {
15023
+ spinner.fail("Fehler beim Laden");
15024
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15025
+ }
15026
+ });
15027
+ 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) => {
15028
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
15029
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
15030
+ if (!isAuthenticated2()) {
15031
+ log.error("Nicht angemeldet");
15032
+ log.info("Anmelden mit: shiva login");
15033
+ return;
15034
+ }
15035
+ const ora24 = (await import("ora")).default;
15036
+ const spinner = ora24("Erstelle Cloud-Hook...").start();
15037
+ try {
15038
+ const result = await api2.createHook({
15039
+ event: options.event,
15040
+ command: options.command,
15041
+ matcher: options.matcher,
15042
+ type: options.type,
15043
+ timeout: options.timeout ? parseInt(options.timeout) : void 0
15044
+ });
15045
+ if (result.success) {
15046
+ spinner.succeed(`Hook erstellt: ${result.hookId}`);
15047
+ } else {
15048
+ spinner.fail(result.message || "Fehler beim Erstellen");
15049
+ }
15050
+ } catch (error) {
15051
+ spinner.fail("Fehler beim Erstellen");
15052
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15053
+ }
15054
+ });
15055
+ hookCommand.command("cloud-test").description("Cloud-Hook testen").argument("<hook-id>", "Hook ID").action(async (hookId) => {
15056
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
15057
+ const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
15058
+ const { colors: colors3 } = await import("./logger-E7SC5KUO.js");
15059
+ if (!isAuthenticated2()) {
15060
+ log.error("Nicht angemeldet");
15061
+ log.info("Anmelden mit: shiva login");
15062
+ return;
15063
+ }
15064
+ const ora24 = (await import("ora")).default;
15065
+ const spinner = ora24("Teste Hook...").start();
15066
+ try {
15067
+ const result = await api2.testHook(hookId);
15068
+ spinner.stop();
15069
+ log.newline();
15070
+ if (result.success) {
15071
+ log.success(`Hook erfolgreich (${result.duration}ms)`);
15072
+ if (result.output) {
15073
+ log.newline();
15074
+ console.log(colors3.dim("Output:"));
15075
+ console.log(result.output);
15076
+ }
15077
+ } else {
15078
+ log.error(`Hook fehlgeschlagen (${result.duration}ms)`);
15079
+ if (result.error) {
15080
+ log.newline();
15081
+ console.log(colors3.dim("Error:"));
15082
+ console.log(colors3.red(result.error));
15083
+ }
15084
+ }
14400
15085
  } catch (error) {
14401
- log.error(error instanceof Error ? error.message : "Fehler beim Sichern");
15086
+ spinner.fail("Fehler beim Testen");
15087
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
14402
15088
  }
14403
15089
  });
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");
15090
+ hookCommand.command("cloud-delete").description("Cloud-Hook l\xF6schen").argument("<hook-id>", "Hook ID").option("-y, --yes", "Ohne Best\xE4tigung").action(async (hookId, options) => {
15091
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14406
15092
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14407
15093
  if (!isAuthenticated2()) {
14408
15094
  log.error("Nicht angemeldet");
14409
15095
  log.info("Anmelden mit: shiva login");
14410
15096
  return;
14411
15097
  }
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");
15098
+ if (!options.yes) {
15099
+ const inquirer14 = (await import("inquirer")).default;
15100
+ const { confirm } = await inquirer14.prompt([{
15101
+ type: "confirm",
15102
+ name: "confirm",
15103
+ message: `Hook ${hookId} l\xF6schen?`,
15104
+ default: false
15105
+ }]);
15106
+ if (!confirm) {
15107
+ log.dim("Abgebrochen");
14422
15108
  return;
14423
15109
  }
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)`);
15110
+ }
15111
+ const ora24 = (await import("ora")).default;
15112
+ const spinner = ora24("L\xF6sche Hook...").start();
15113
+ try {
15114
+ const result = await api2.deleteHook(hookId);
15115
+ if (result.success) {
15116
+ spinner.succeed("Hook gel\xF6scht");
15117
+ } else {
15118
+ spinner.fail(result.message || "Fehler beim L\xF6schen");
14431
15119
  }
14432
15120
  } catch (error) {
14433
- log.error(error instanceof Error ? error.message : "Fehler beim Laden");
15121
+ spinner.fail("Fehler beim L\xF6schen");
15122
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
14434
15123
  }
14435
15124
  });
14436
- hookCommand.command("sync").description("Hooks mit Cloud synchronisieren").action(async () => {
14437
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
15125
+ 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) => {
15126
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14438
15127
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14439
15128
  if (!isAuthenticated2()) {
14440
15129
  log.error("Nicht angemeldet");
14441
15130
  log.info("Anmelden mit: shiva login");
14442
15131
  return;
14443
15132
  }
14444
- const settings = getClaudeSettings();
15133
+ const enabled = options.enable ? true : options.disable ? false : void 0;
15134
+ if (enabled === void 0) {
15135
+ log.error("Bitte --enable oder --disable angeben");
15136
+ return;
15137
+ }
15138
+ const ora24 = (await import("ora")).default;
15139
+ const spinner = ora24("Aktualisiere Hook...").start();
14445
15140
  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)");
15141
+ const result = await api2.updateHook(hookId, { enabled });
15142
+ if (result.success) {
15143
+ spinner.succeed(`Hook ${enabled ? "aktiviert" : "deaktiviert"}`);
15144
+ } else {
15145
+ spinner.fail(result.message || "Fehler beim Aktualisieren");
14456
15146
  }
14457
- log.newline();
14458
- log.success("Hooks synchronisiert");
14459
15147
  } catch (error) {
14460
- log.error(error instanceof Error ? error.message : "Fehler beim Synchronisieren");
15148
+ spinner.fail("Fehler beim Aktualisieren");
15149
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
14461
15150
  }
14462
15151
  });
14463
15152
 
14464
15153
  // src/commands/advanced/package.ts
14465
- import { Command as Command35 } from "commander";
15154
+ import { Command as Command36 } from "commander";
14466
15155
  import * as fs14 from "fs";
14467
15156
  import inquirer13 from "inquirer";
14468
- import ora21 from "ora";
14469
- var packageCommand = new Command35("package").description("Projekt-Gruppen (Packages) verwalten").action(() => {
15157
+ import ora22 from "ora";
15158
+ var packageCommand = new Command36("package").description("Projekt-Gruppen (Packages) verwalten").action(() => {
14470
15159
  listPackages();
14471
15160
  });
14472
15161
  packageCommand.command("list").description("Alle Packages auflisten").option("--json", "JSON Output").action((options) => {
@@ -14582,7 +15271,7 @@ packageCommand.command("start <name>").description("Alle Projekte eines Packages
14582
15271
  log.error(`Package "${pkg.name}" hat keine Projekte.`);
14583
15272
  return;
14584
15273
  }
14585
- const spinner = ora21("Bereite Projekte vor...").start();
15274
+ const spinner = ora22("Bereite Projekte vor...").start();
14586
15275
  try {
14587
15276
  const launches = await getPackageLaunchConfig(name, options.new);
14588
15277
  spinner.stop();
@@ -14611,7 +15300,7 @@ packageCommand.command("start <name>").description("Alle Projekte eines Packages
14611
15300
  }
14612
15301
  });
14613
15302
  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");
15303
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14615
15304
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14616
15305
  if (!isAuthenticated2()) {
14617
15306
  log.error("Nicht angemeldet");
@@ -14632,7 +15321,7 @@ packageCommand.command("push").description("Packages in Cloud sichern").option("
14632
15321
  log.warn("Keine Packages zum Synchronisieren gefunden");
14633
15322
  return;
14634
15323
  }
14635
- const spinner = ora21("Synchronisiere Packages...").start();
15324
+ const spinner = ora22("Synchronisiere Packages...").start();
14636
15325
  let syncedCount = 0;
14637
15326
  let errorCount = 0;
14638
15327
  for (const pkg of packages) {
@@ -14657,14 +15346,14 @@ packageCommand.command("push").description("Packages in Cloud sichern").option("
14657
15346
  }
14658
15347
  });
14659
15348
  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");
15349
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14661
15350
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14662
15351
  if (!isAuthenticated2()) {
14663
15352
  log.error("Nicht angemeldet");
14664
15353
  log.info("Anmelden mit: shiva login");
14665
15354
  return;
14666
15355
  }
14667
- const spinner = ora21("Lade Packages aus Cloud...").start();
15356
+ const spinner = ora22("Lade Packages aus Cloud...").start();
14668
15357
  try {
14669
15358
  const cloudPackages = await api2.getPackages();
14670
15359
  spinner.stop();
@@ -14719,14 +15408,14 @@ packageCommand.command("pull").description("Packages aus Cloud laden").option("-
14719
15408
  }
14720
15409
  });
14721
15410
  packageCommand.command("sync").description("Packages mit Cloud synchronisieren").action(async () => {
14722
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
15411
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14723
15412
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14724
15413
  if (!isAuthenticated2()) {
14725
15414
  log.error("Nicht angemeldet");
14726
15415
  log.info("Anmelden mit: shiva login");
14727
15416
  return;
14728
15417
  }
14729
- const spinner = ora21("Synchronisiere Packages...").start();
15418
+ const spinner = ora22("Synchronisiere Packages...").start();
14730
15419
  const localPackages = getAllPackages();
14731
15420
  let pushedCount = 0;
14732
15421
  for (const pkg of localPackages) {
@@ -14772,7 +15461,7 @@ packageCommand.command("sync").description("Packages mit Cloud synchronisieren")
14772
15461
  log.tree.item(`${localPackages.length + pulledCount} Packages total`);
14773
15462
  });
14774
15463
  packageCommand.command("cloud-delete <name>").description("Package aus Cloud l\xF6schen").action(async (name) => {
14775
- const { api: api2 } = await import("./client-2L7NWNCZ.js");
15464
+ const { api: api2 } = await import("./client-UPSJM4FM.js");
14776
15465
  const { isAuthenticated: isAuthenticated2 } = await import("./config-FGMZONWV.js");
14777
15466
  if (!isAuthenticated2()) {
14778
15467
  log.error("Nicht angemeldet");
@@ -14828,8 +15517,361 @@ function listPackages() {
14828
15517
  log.newline();
14829
15518
  }
14830
15519
 
15520
+ // src/commands/advanced/sandbox.ts
15521
+ import { Command as Command37 } from "commander";
15522
+ import ora23 from "ora";
15523
+ var sandboxCommand = new Command37("sandbox").description("Sandbox-Management mit Cloud-Sync");
15524
+ 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) => {
15525
+ const spinner = ora23("Lade Sandboxes...").start();
15526
+ try {
15527
+ const results = [];
15528
+ if (!options.cloud) {
15529
+ const localSandboxes = sandboxService.listSandboxes();
15530
+ for (const sandbox of localSandboxes) {
15531
+ if (!options.status || sandbox.status === options.status) {
15532
+ results.push({
15533
+ id: sandbox.id,
15534
+ source: "local",
15535
+ status: sandbox.status,
15536
+ mode: sandbox.mode,
15537
+ projectPath: sandbox.projectPath,
15538
+ createdAt: sandbox.createdAt
15539
+ });
15540
+ }
15541
+ }
15542
+ }
15543
+ if (!options.local && isAuthenticated()) {
15544
+ try {
15545
+ const cloudSandboxes = await api.getSandboxes(
15546
+ options.status ? { status: options.status } : void 0
15547
+ );
15548
+ for (const sandbox of cloudSandboxes) {
15549
+ results.push({
15550
+ id: sandbox.id,
15551
+ source: "cloud",
15552
+ status: sandbox.status,
15553
+ mode: sandbox.mode,
15554
+ projectId: sandbox.projectId,
15555
+ createdAt: sandbox.createdAt,
15556
+ title: sandbox.title
15557
+ });
15558
+ }
15559
+ } catch {
15560
+ }
15561
+ }
15562
+ spinner.stop();
15563
+ if (options.json) {
15564
+ console.log(JSON.stringify(results, null, 2));
15565
+ return;
15566
+ }
15567
+ log.newline();
15568
+ console.log(colors.orange.bold("Sandboxes"));
15569
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
15570
+ log.newline();
15571
+ if (results.length === 0) {
15572
+ log.dim("Keine Sandboxes gefunden");
15573
+ return;
15574
+ }
15575
+ for (const sandbox of results) {
15576
+ const statusColor = sandbox.status === "active" ? colors.green : sandbox.status === "pending-review" ? colors.yellow : colors.dim;
15577
+ const sourceIcon = sandbox.source === "cloud" ? colors.cyan("\u2601") : colors.dim("\u{1F4BB}");
15578
+ console.log(` ${sourceIcon} ${colors.bold(sandbox.id)} ${statusColor(`[${sandbox.status}]`)}`);
15579
+ console.log(` ${colors.dim("Mode:")} ${sandbox.mode}`);
15580
+ if (sandbox.title) {
15581
+ console.log(` ${colors.dim("Title:")} ${sandbox.title}`);
15582
+ }
15583
+ if (sandbox.projectPath) {
15584
+ console.log(` ${colors.dim("Project:")} ${sandbox.projectPath}`);
15585
+ }
15586
+ console.log(` ${colors.dim("Created:")} ${sandbox.createdAt}`);
15587
+ log.newline();
15588
+ }
15589
+ } catch (error) {
15590
+ spinner.fail("Fehler beim Laden");
15591
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15592
+ }
15593
+ });
15594
+ sandboxCommand.command("pending").description("Sandboxes mit Pending Review Status").option("--json", "JSON Output").action(async (options) => {
15595
+ const spinner = ora23("Lade Pending Sandboxes...").start();
15596
+ try {
15597
+ const localPending = sandboxService.listPendingReview();
15598
+ let cloudPending = [];
15599
+ if (isAuthenticated()) {
15600
+ try {
15601
+ cloudPending = await api.getPendingSandboxes();
15602
+ } catch {
15603
+ }
15604
+ }
15605
+ spinner.stop();
15606
+ if (options.json) {
15607
+ console.log(JSON.stringify({ local: localPending, cloud: cloudPending }, null, 2));
15608
+ return;
15609
+ }
15610
+ log.newline();
15611
+ console.log(colors.orange.bold("Pending Review"));
15612
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
15613
+ log.newline();
15614
+ if (localPending.length === 0 && cloudPending.length === 0) {
15615
+ log.dim("Keine Sandboxes zum Review");
15616
+ return;
15617
+ }
15618
+ if (localPending.length > 0) {
15619
+ console.log(colors.dim("Local:"));
15620
+ for (const sandbox of localPending) {
15621
+ console.log(` ${colors.yellow("\u25CB")} ${sandbox.id} - ${sandbox.projectPath}`);
15622
+ }
15623
+ log.newline();
15624
+ }
15625
+ if (cloudPending.length > 0) {
15626
+ console.log(colors.dim("Cloud:"));
15627
+ for (const sandbox of cloudPending) {
15628
+ console.log(` ${colors.cyan("\u2601")} ${sandbox.id} - ${sandbox.title || sandbox.baseBranch}`);
15629
+ }
15630
+ log.newline();
15631
+ }
15632
+ log.info("Review mit: shiva session review <id>");
15633
+ } catch (error) {
15634
+ spinner.fail("Fehler beim Laden");
15635
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15636
+ }
15637
+ });
15638
+ sandboxCommand.command("stats").description("Sandbox-Statistiken anzeigen").option("--json", "JSON Output").action(async (options) => {
15639
+ const spinner = ora23("Lade Statistiken...").start();
15640
+ try {
15641
+ const localSandboxes = sandboxService.listSandboxes();
15642
+ const localStats = {
15643
+ total: localSandboxes.length,
15644
+ active: localSandboxes.filter((s) => s.status === "active").length,
15645
+ pendingReview: localSandboxes.filter((s) => s.status === "pending-review").length,
15646
+ applied: localSandboxes.filter((s) => s.status === "applied").length,
15647
+ discarded: localSandboxes.filter((s) => s.status === "discarded").length
15648
+ };
15649
+ let cloudStats = { total: 0, active: 0, pendingReview: 0, applied: 0, discarded: 0 };
15650
+ if (isAuthenticated()) {
15651
+ try {
15652
+ cloudStats = await api.getSandboxStats();
15653
+ } catch {
15654
+ }
15655
+ }
15656
+ spinner.stop();
15657
+ if (options.json) {
15658
+ console.log(JSON.stringify({ local: localStats, cloud: cloudStats }, null, 2));
15659
+ return;
15660
+ }
15661
+ log.newline();
15662
+ console.log(colors.orange.bold("Sandbox Statistics"));
15663
+ console.log(colors.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
15664
+ log.newline();
15665
+ console.log(colors.bold("Local:"));
15666
+ console.log(` ${colors.dim("Total:")} ${localStats.total}`);
15667
+ console.log(` ${colors.green("Active:")} ${localStats.active}`);
15668
+ console.log(` ${colors.yellow("Pending:")} ${localStats.pendingReview}`);
15669
+ console.log(` ${colors.dim("Applied:")} ${localStats.applied}`);
15670
+ console.log(` ${colors.dim("Discarded:")} ${localStats.discarded}`);
15671
+ log.newline();
15672
+ if (isAuthenticated()) {
15673
+ console.log(colors.bold("Cloud:"));
15674
+ console.log(` ${colors.dim("Total:")} ${cloudStats.total}`);
15675
+ console.log(` ${colors.green("Active:")} ${cloudStats.active}`);
15676
+ console.log(` ${colors.yellow("Pending:")} ${cloudStats.pendingReview}`);
15677
+ console.log(` ${colors.dim("Applied:")} ${cloudStats.applied}`);
15678
+ console.log(` ${colors.dim("Discarded:")} ${cloudStats.discarded}`);
15679
+ } else {
15680
+ log.dim("Cloud-Statistiken: Nicht angemeldet");
15681
+ }
15682
+ } catch (error) {
15683
+ spinner.fail("Fehler beim Laden");
15684
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15685
+ }
15686
+ });
15687
+ 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) => {
15688
+ if (!isAuthenticated()) {
15689
+ log.error("Nicht angemeldet");
15690
+ log.info("Anmelden mit: shiva login");
15691
+ return;
15692
+ }
15693
+ const spinner = ora23("Synchronisiere Sandbox...").start();
15694
+ try {
15695
+ if (id) {
15696
+ await api.syncSandbox(id, {
15697
+ status: options.status
15698
+ });
15699
+ spinner.succeed(`Sandbox ${id} synchronisiert`);
15700
+ } else {
15701
+ const localSandboxes = sandboxService.listSandboxes();
15702
+ let synced = 0;
15703
+ for (const sandbox of localSandboxes) {
15704
+ try {
15705
+ await api.syncSandbox(sandbox.id, {
15706
+ status: sandbox.status === "active" ? void 0 : sandbox.status
15707
+ });
15708
+ synced++;
15709
+ } catch {
15710
+ }
15711
+ }
15712
+ spinner.succeed(`${synced}/${localSandboxes.length} Sandboxes synchronisiert`);
15713
+ }
15714
+ } catch (error) {
15715
+ spinner.fail("Fehler beim Synchronisieren");
15716
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15717
+ }
15718
+ });
15719
+ 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) => {
15720
+ const days = parseInt(options.days);
15721
+ if (!options.yes) {
15722
+ const { default: inquirer14 } = await import("inquirer");
15723
+ const { confirm } = await inquirer14.prompt([{
15724
+ type: "confirm",
15725
+ name: "confirm",
15726
+ message: `Sandboxes \xE4lter als ${days} Tage l\xF6schen?`,
15727
+ default: false
15728
+ }]);
15729
+ if (!confirm) {
15730
+ log.dim("Abgebrochen");
15731
+ return;
15732
+ }
15733
+ }
15734
+ const spinner = ora23("R\xE4ume Sandboxes auf...").start();
15735
+ try {
15736
+ let localDeleted = 0;
15737
+ let cloudDeleted = 0;
15738
+ if (!options.cloud) {
15739
+ localDeleted = await sandboxService.cleanupOldSandboxes(days);
15740
+ }
15741
+ if (!options.local && isAuthenticated()) {
15742
+ try {
15743
+ const result = await api.cleanupSandboxes({ olderThanDays: days });
15744
+ cloudDeleted = result.deletedCount;
15745
+ } catch {
15746
+ }
15747
+ }
15748
+ spinner.stop();
15749
+ log.success("Cleanup abgeschlossen");
15750
+ log.newline();
15751
+ log.keyValue("Lokal gel\xF6scht", String(localDeleted));
15752
+ if (!options.local) {
15753
+ log.keyValue("Cloud gel\xF6scht", String(cloudDeleted));
15754
+ }
15755
+ } catch (error) {
15756
+ spinner.fail("Fehler beim Aufr\xE4umen");
15757
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15758
+ }
15759
+ });
15760
+ 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) => {
15761
+ if (options.pull && isAuthenticated()) {
15762
+ const spinner = ora23("Lade Konfiguration aus Cloud...").start();
15763
+ try {
15764
+ const cloudConfig = await api.getSandboxConfig();
15765
+ sandboxService.updateConfig({
15766
+ defaultMode: cloudConfig.defaultMode,
15767
+ keepDays: cloudConfig.autoCleanupDays,
15768
+ maxSandboxes: cloudConfig.maxActiveSandboxes
15769
+ });
15770
+ spinner.succeed("Konfiguration aus Cloud geladen");
15771
+ return;
15772
+ } catch (error) {
15773
+ spinner.fail("Fehler beim Laden aus Cloud");
15774
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15775
+ return;
15776
+ }
15777
+ }
15778
+ if (options.push && isAuthenticated()) {
15779
+ const spinner = ora23("Speichere Konfiguration in Cloud...").start();
15780
+ try {
15781
+ const localConfig = sandboxService.getConfig();
15782
+ const cloudMode = localConfig.defaultMode === "none" ? "worktree" : localConfig.defaultMode;
15783
+ await api.updateSandboxConfig({
15784
+ defaultMode: cloudMode,
15785
+ autoCleanupDays: localConfig.keepDays,
15786
+ maxActiveSandboxes: localConfig.maxSandboxes,
15787
+ requireReview: options.requireReview ?? true
15788
+ });
15789
+ spinner.succeed("Konfiguration in Cloud gespeichert");
15790
+ return;
15791
+ } catch (error) {
15792
+ spinner.fail("Fehler beim Speichern in Cloud");
15793
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15794
+ return;
15795
+ }
15796
+ }
15797
+ if (options.show || !options.mode && !options.cleanupDays && !options.max && options.requireReview === void 0) {
15798
+ const config = sandboxService.getConfig();
15799
+ log.newline();
15800
+ console.log(colors.orange.bold("Sandbox Configuration"));
15801
+ 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"));
15802
+ log.newline();
15803
+ log.keyValue("Enabled", config.enabled ? colors.green("Yes") : colors.red("No"));
15804
+ log.keyValue("Default Mode", config.defaultMode);
15805
+ log.keyValue("Auto Cleanup", config.autoCleanup ? "Yes" : "No");
15806
+ log.keyValue("Keep Days", String(config.keepDays));
15807
+ log.keyValue("Max Sandboxes", String(config.maxSandboxes));
15808
+ log.newline();
15809
+ if (isAuthenticated()) {
15810
+ try {
15811
+ const cloudConfig = await api.getSandboxConfig();
15812
+ console.log(colors.bold("Cloud Config:"));
15813
+ log.keyValue(" Default Mode", cloudConfig.defaultMode);
15814
+ log.keyValue(" Cleanup Days", String(cloudConfig.autoCleanupDays));
15815
+ log.keyValue(" Max Active", String(cloudConfig.maxActiveSandboxes));
15816
+ log.keyValue(" Require Review", cloudConfig.requireReview ? "Yes" : "No");
15817
+ } catch {
15818
+ log.dim("Cloud-Konfiguration nicht verf\xFCgbar");
15819
+ }
15820
+ }
15821
+ return;
15822
+ }
15823
+ const updates = {};
15824
+ if (options.mode) {
15825
+ updates.defaultMode = options.mode;
15826
+ }
15827
+ if (options.cleanupDays) {
15828
+ updates.keepDays = parseInt(options.cleanupDays);
15829
+ }
15830
+ if (options.max) {
15831
+ updates.maxSandboxes = parseInt(options.max);
15832
+ }
15833
+ sandboxService.updateConfig(updates);
15834
+ log.success("Konfiguration aktualisiert");
15835
+ });
15836
+ 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) => {
15837
+ if (!options.yes) {
15838
+ const { default: inquirer14 } = await import("inquirer");
15839
+ const { confirm } = await inquirer14.prompt([{
15840
+ type: "confirm",
15841
+ name: "confirm",
15842
+ message: `Sandbox ${id} l\xF6schen?`,
15843
+ default: false
15844
+ }]);
15845
+ if (!confirm) {
15846
+ log.dim("Abgebrochen");
15847
+ return;
15848
+ }
15849
+ }
15850
+ const spinner = ora23("L\xF6sche Sandbox...").start();
15851
+ try {
15852
+ try {
15853
+ await sandboxService.deleteSandbox(id);
15854
+ spinner.text = "Lokal gel\xF6scht";
15855
+ } catch {
15856
+ }
15857
+ if (options.cloud || isAuthenticated()) {
15858
+ try {
15859
+ await api.deleteSandbox(id);
15860
+ spinner.succeed("Sandbox gel\xF6scht (lokal + cloud)");
15861
+ } catch {
15862
+ spinner.succeed("Sandbox gel\xF6scht (lokal)");
15863
+ }
15864
+ } else {
15865
+ spinner.succeed("Sandbox gel\xF6scht");
15866
+ }
15867
+ } catch (error) {
15868
+ spinner.fail("Fehler beim L\xF6schen");
15869
+ log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
15870
+ }
15871
+ });
15872
+
14831
15873
  // src/index.ts
14832
- var program = new Command36();
15874
+ var program = new Command38();
14833
15875
  program.name("shiva").description("SHIVA Code - Control Station for Claude Code").version("0.5.4");
14834
15876
  program.addCommand(loginCommand);
14835
15877
  program.addCommand(logoutCommand);
@@ -14869,6 +15911,8 @@ program.addCommand(dockerCommand);
14869
15911
  program.addCommand(workflowCommand);
14870
15912
  program.addCommand(hookCommand);
14871
15913
  program.addCommand(packageCommand);
15914
+ program.addCommand(sandboxCommand);
15915
+ program.addCommand(userCommand);
14872
15916
  program.action(async () => {
14873
15917
  await showDashboard();
14874
15918
  });