shiva-code 0.1.0 → 0.2.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 +195 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command10 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/login.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -656,27 +656,31 @@ import { Command as Command4 } from "commander";
|
|
|
656
656
|
import { writeFileSync as writeFileSync2, existsSync as existsSync3 } from "fs";
|
|
657
657
|
import { resolve as resolve3 } from "path";
|
|
658
658
|
import ora2 from "ora";
|
|
659
|
-
var syncCommand = new Command4("sync").description("Projekt mit Cloud synchronisieren").option("-d, --dir <directory>", "Projektverzeichnis", ".").option("--pull", "Nur von Cloud herunterladen").option("--push", "Nur zu Cloud hochladen").action(async (options) => {
|
|
659
|
+
var syncCommand = new Command4("sync").description("Projekt mit Cloud synchronisieren").option("-d, --dir <directory>", "Projektverzeichnis", ".").option("--pull", "Nur von Cloud herunterladen").option("--push", "Nur zu Cloud hochladen").option("-q, --quiet", "Keine Ausgabe (f\xFCr Hooks)").action(async (options) => {
|
|
660
|
+
const quiet = options.quiet;
|
|
660
661
|
if (!isAuthenticated()) {
|
|
661
|
-
log.error('Nicht angemeldet. Bitte zuerst "shiva login" ausf\xFChren.');
|
|
662
|
+
if (!quiet) log.error('Nicht angemeldet. Bitte zuerst "shiva login" ausf\xFChren.');
|
|
663
|
+
process.exit(1);
|
|
662
664
|
return;
|
|
663
665
|
}
|
|
664
666
|
const projectDir = resolve3(options.dir);
|
|
665
667
|
if (!existsSync3(projectDir)) {
|
|
666
|
-
log.error(`Verzeichnis nicht gefunden: ${projectDir}`);
|
|
668
|
+
if (!quiet) log.error(`Verzeichnis nicht gefunden: ${projectDir}`);
|
|
669
|
+
process.exit(1);
|
|
667
670
|
return;
|
|
668
671
|
}
|
|
669
|
-
const spinner = ora2("Synchronisiere...").start();
|
|
672
|
+
const spinner = quiet ? null : ora2("Synchronisiere...").start();
|
|
670
673
|
let scanned;
|
|
671
674
|
try {
|
|
672
675
|
scanned = await scanProject(projectDir);
|
|
673
676
|
} catch (error) {
|
|
674
|
-
spinner
|
|
677
|
+
spinner?.fail("Fehler beim Scannen");
|
|
678
|
+
process.exit(1);
|
|
675
679
|
return;
|
|
676
680
|
}
|
|
677
681
|
let project = await api.findProjectByPath(scanned.path);
|
|
678
682
|
if (!project) {
|
|
679
|
-
spinner.text = "Erstelle Projekt...";
|
|
683
|
+
if (spinner) spinner.text = "Erstelle Projekt...";
|
|
680
684
|
try {
|
|
681
685
|
const result = await api.createOrUpdateProject({
|
|
682
686
|
name: scanned.name,
|
|
@@ -691,8 +695,9 @@ var syncCommand = new Command4("sync").description("Projekt mit Cloud synchronis
|
|
|
691
695
|
});
|
|
692
696
|
project = await api.getProject(result.projectId);
|
|
693
697
|
} catch (error) {
|
|
694
|
-
spinner
|
|
695
|
-
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
698
|
+
spinner?.fail("Fehler beim Erstellen");
|
|
699
|
+
if (!quiet) log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
700
|
+
process.exit(1);
|
|
696
701
|
return;
|
|
697
702
|
}
|
|
698
703
|
}
|
|
@@ -702,7 +707,7 @@ var syncCommand = new Command4("sync").description("Projekt mit Cloud synchronis
|
|
|
702
707
|
memories = parsed.memories;
|
|
703
708
|
}
|
|
704
709
|
if (!options.pull) {
|
|
705
|
-
spinner.text = "Hochladen...";
|
|
710
|
+
if (spinner) spinner.text = "Hochladen...";
|
|
706
711
|
try {
|
|
707
712
|
await api.syncProject(project.id, {
|
|
708
713
|
claude_md_content: scanned.claudeMdContent,
|
|
@@ -714,31 +719,35 @@ var syncCommand = new Command4("sync").description("Projekt mit Cloud synchronis
|
|
|
714
719
|
memories
|
|
715
720
|
});
|
|
716
721
|
} catch (error) {
|
|
717
|
-
spinner
|
|
718
|
-
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
722
|
+
spinner?.fail("Fehler beim Hochladen");
|
|
723
|
+
if (!quiet) log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
724
|
+
process.exit(1);
|
|
719
725
|
return;
|
|
720
726
|
}
|
|
721
727
|
}
|
|
722
728
|
if (!options.push) {
|
|
723
|
-
spinner.text = "Aktualisiere CLAUDE.md...";
|
|
729
|
+
if (spinner) spinner.text = "Aktualisiere CLAUDE.md...";
|
|
724
730
|
try {
|
|
725
731
|
project = await api.getProject(project.id);
|
|
726
732
|
const newClaudeMd = generateClaudeMd(scanned, project);
|
|
727
733
|
const claudeMdPath = resolve3(projectDir, "CLAUDE.md");
|
|
728
734
|
writeFileSync2(claudeMdPath, newClaudeMd);
|
|
729
735
|
} catch (error) {
|
|
730
|
-
spinner
|
|
731
|
-
log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
736
|
+
spinner?.fail("Fehler beim Aktualisieren");
|
|
737
|
+
if (!quiet) log.error(error instanceof Error ? error.message : "Unbekannter Fehler");
|
|
738
|
+
process.exit(1);
|
|
732
739
|
return;
|
|
733
740
|
}
|
|
734
741
|
}
|
|
735
|
-
spinner
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
+
spinner?.succeed("Synchronisiert");
|
|
743
|
+
if (!quiet) {
|
|
744
|
+
log.newline();
|
|
745
|
+
log.tree.item("CLAUDE.md aktualisiert");
|
|
746
|
+
log.tree.item(`${project.memories?.length || 0} Memories synchronisiert`);
|
|
747
|
+
log.tree.item("Metadata aktualisiert", true);
|
|
748
|
+
log.newline();
|
|
749
|
+
log.success(`Sync erfolgreich (${(/* @__PURE__ */ new Date()).toLocaleTimeString()})`);
|
|
750
|
+
}
|
|
742
751
|
});
|
|
743
752
|
|
|
744
753
|
// src/commands/status.ts
|
|
@@ -1103,8 +1112,169 @@ configCommand.command("reset").description("Konfiguration zur\xFCcksetzen").acti
|
|
|
1103
1112
|
log.success("Konfiguration zur\xFCckgesetzt");
|
|
1104
1113
|
});
|
|
1105
1114
|
|
|
1115
|
+
// src/commands/hook.ts
|
|
1116
|
+
import { Command as Command9 } from "commander";
|
|
1117
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync } from "fs";
|
|
1118
|
+
import { homedir } from "os";
|
|
1119
|
+
import { join } from "path";
|
|
1120
|
+
var CLAUDE_SETTINGS_PATH = join(homedir(), ".claude", "settings.json");
|
|
1121
|
+
function getClaudeSettings() {
|
|
1122
|
+
if (!existsSync6(CLAUDE_SETTINGS_PATH)) {
|
|
1123
|
+
return {};
|
|
1124
|
+
}
|
|
1125
|
+
try {
|
|
1126
|
+
const content = readFileSync3(CLAUDE_SETTINGS_PATH, "utf-8");
|
|
1127
|
+
return JSON.parse(content);
|
|
1128
|
+
} catch {
|
|
1129
|
+
return {};
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
function saveClaudeSettings(settings) {
|
|
1133
|
+
const dir = join(homedir(), ".claude");
|
|
1134
|
+
if (!existsSync6(dir)) {
|
|
1135
|
+
mkdirSync(dir, { recursive: true });
|
|
1136
|
+
}
|
|
1137
|
+
writeFileSync3(CLAUDE_SETTINGS_PATH, JSON.stringify(settings, null, 2));
|
|
1138
|
+
}
|
|
1139
|
+
function hasShivaHook(hooks, event) {
|
|
1140
|
+
if (!hooks || !hooks[event]) return false;
|
|
1141
|
+
const eventHooks = hooks[event];
|
|
1142
|
+
return eventHooks.some(
|
|
1143
|
+
(entry) => entry.hooks?.some((h) => h.command?.includes("shiva"))
|
|
1144
|
+
);
|
|
1145
|
+
}
|
|
1146
|
+
function removeShivaHooks(eventHooks) {
|
|
1147
|
+
return eventHooks.filter(
|
|
1148
|
+
(entry) => !entry.hooks?.some((h) => h.command?.includes("shiva"))
|
|
1149
|
+
);
|
|
1150
|
+
}
|
|
1151
|
+
var hookCommand = new Command9("hook").description("Claude Code Hook Integration verwalten");
|
|
1152
|
+
hookCommand.command("install").description("SHIVA Hooks in Claude Code installieren").action(() => {
|
|
1153
|
+
log.brand();
|
|
1154
|
+
const claudePath = join(homedir(), ".claude");
|
|
1155
|
+
if (!existsSync6(claudePath)) {
|
|
1156
|
+
log.error("Claude Code nicht gefunden");
|
|
1157
|
+
log.newline();
|
|
1158
|
+
log.info("Installiere Claude Code:");
|
|
1159
|
+
log.plain(" npm install -g @anthropic-ai/claude-code");
|
|
1160
|
+
log.newline();
|
|
1161
|
+
log.dim("Oder: https://claude.ai/code");
|
|
1162
|
+
return;
|
|
1163
|
+
}
|
|
1164
|
+
const settings = getClaudeSettings();
|
|
1165
|
+
if (!settings.hooks) {
|
|
1166
|
+
settings.hooks = {};
|
|
1167
|
+
}
|
|
1168
|
+
if (hasShivaHook(settings.hooks, "SessionStart") || hasShivaHook(settings.hooks, "Stop")) {
|
|
1169
|
+
log.warn("SHIVA Hooks sind bereits installiert");
|
|
1170
|
+
log.newline();
|
|
1171
|
+
log.info("Zum Neuinstallieren:");
|
|
1172
|
+
log.plain(" shiva hook uninstall");
|
|
1173
|
+
log.plain(" shiva hook install");
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
if (!settings.hooks.SessionStart) {
|
|
1177
|
+
settings.hooks.SessionStart = [];
|
|
1178
|
+
}
|
|
1179
|
+
settings.hooks.SessionStart.push({
|
|
1180
|
+
matcher: {},
|
|
1181
|
+
hooks: [
|
|
1182
|
+
{
|
|
1183
|
+
type: "command",
|
|
1184
|
+
command: "shiva sync --pull --quiet"
|
|
1185
|
+
}
|
|
1186
|
+
]
|
|
1187
|
+
});
|
|
1188
|
+
if (!settings.hooks.Stop) {
|
|
1189
|
+
settings.hooks.Stop = [];
|
|
1190
|
+
}
|
|
1191
|
+
settings.hooks.Stop.push({
|
|
1192
|
+
matcher: {},
|
|
1193
|
+
hooks: [
|
|
1194
|
+
{
|
|
1195
|
+
type: "command",
|
|
1196
|
+
command: "shiva sync --push --quiet"
|
|
1197
|
+
}
|
|
1198
|
+
]
|
|
1199
|
+
});
|
|
1200
|
+
saveClaudeSettings(settings);
|
|
1201
|
+
log.success("SHIVA Hooks installiert!");
|
|
1202
|
+
log.newline();
|
|
1203
|
+
log.header("Aktive Hooks");
|
|
1204
|
+
log.tree.item("SessionStart: Memories laden");
|
|
1205
|
+
log.tree.item("Stop: Memories speichern", true);
|
|
1206
|
+
log.newline();
|
|
1207
|
+
log.dim("Claude Code wird nun automatisch mit SHIVA synchronisiert.");
|
|
1208
|
+
log.newline();
|
|
1209
|
+
log.info("Starte Claude Code wie gewohnt:");
|
|
1210
|
+
log.plain(" claude");
|
|
1211
|
+
});
|
|
1212
|
+
hookCommand.command("uninstall").description("SHIVA Hooks aus Claude Code entfernen").action(() => {
|
|
1213
|
+
log.brand();
|
|
1214
|
+
const settings = getClaudeSettings();
|
|
1215
|
+
if (!settings.hooks) {
|
|
1216
|
+
log.info("Keine Hooks installiert");
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
let removed = false;
|
|
1220
|
+
if (settings.hooks.SessionStart) {
|
|
1221
|
+
const before = settings.hooks.SessionStart.length;
|
|
1222
|
+
settings.hooks.SessionStart = removeShivaHooks(settings.hooks.SessionStart);
|
|
1223
|
+
if (settings.hooks.SessionStart.length < before) removed = true;
|
|
1224
|
+
if (settings.hooks.SessionStart.length === 0) delete settings.hooks.SessionStart;
|
|
1225
|
+
}
|
|
1226
|
+
if (settings.hooks.Stop) {
|
|
1227
|
+
const before = settings.hooks.Stop.length;
|
|
1228
|
+
settings.hooks.Stop = removeShivaHooks(settings.hooks.Stop);
|
|
1229
|
+
if (settings.hooks.Stop.length < before) removed = true;
|
|
1230
|
+
if (settings.hooks.Stop.length === 0) delete settings.hooks.Stop;
|
|
1231
|
+
}
|
|
1232
|
+
if (Object.keys(settings.hooks).length === 0) {
|
|
1233
|
+
delete settings.hooks;
|
|
1234
|
+
}
|
|
1235
|
+
saveClaudeSettings(settings);
|
|
1236
|
+
if (removed) {
|
|
1237
|
+
log.success("SHIVA Hooks entfernt");
|
|
1238
|
+
} else {
|
|
1239
|
+
log.info("Keine SHIVA Hooks gefunden");
|
|
1240
|
+
}
|
|
1241
|
+
});
|
|
1242
|
+
hookCommand.command("status").description("Hook-Status anzeigen").action(() => {
|
|
1243
|
+
log.brand();
|
|
1244
|
+
log.header("Hook Status");
|
|
1245
|
+
log.newline();
|
|
1246
|
+
const settings = getClaudeSettings();
|
|
1247
|
+
if (!settings.hooks) {
|
|
1248
|
+
log.listItem("Keine Hooks installiert", "pending");
|
|
1249
|
+
log.newline();
|
|
1250
|
+
log.info("Installieren mit: shiva hook install");
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
const hasSessionStart = hasShivaHook(settings.hooks, "SessionStart");
|
|
1254
|
+
const hasStop = hasShivaHook(settings.hooks, "Stop");
|
|
1255
|
+
if (hasSessionStart) {
|
|
1256
|
+
log.listItem("SessionStart: Memories laden", "synced");
|
|
1257
|
+
} else {
|
|
1258
|
+
log.listItem("SessionStart: nicht aktiv", "pending");
|
|
1259
|
+
}
|
|
1260
|
+
if (hasStop) {
|
|
1261
|
+
log.listItem("Stop: Memories speichern", "synced");
|
|
1262
|
+
} else {
|
|
1263
|
+
log.listItem("Stop: nicht aktiv", "pending");
|
|
1264
|
+
}
|
|
1265
|
+
log.newline();
|
|
1266
|
+
if (hasSessionStart && hasStop) {
|
|
1267
|
+
log.success("SHIVA ist vollst\xE4ndig integriert");
|
|
1268
|
+
} else if (hasSessionStart || hasStop) {
|
|
1269
|
+
log.warn("SHIVA ist teilweise integriert");
|
|
1270
|
+
log.info("Neuinstallation empfohlen: shiva hook install");
|
|
1271
|
+
} else {
|
|
1272
|
+
log.info("Installieren mit: shiva hook install");
|
|
1273
|
+
}
|
|
1274
|
+
});
|
|
1275
|
+
|
|
1106
1276
|
// src/index.ts
|
|
1107
|
-
var program = new
|
|
1277
|
+
var program = new Command10();
|
|
1108
1278
|
program.name("shiva").description("SHIVA Code - Makes Claude Code Persistent").version("0.1.0");
|
|
1109
1279
|
program.addCommand(loginCommand);
|
|
1110
1280
|
program.addCommand(logoutCommand);
|
|
@@ -1115,6 +1285,7 @@ program.addCommand(projectsCommand);
|
|
|
1115
1285
|
program.addCommand(connectCommand);
|
|
1116
1286
|
program.addCommand(disconnectCommand);
|
|
1117
1287
|
program.addCommand(configCommand);
|
|
1288
|
+
program.addCommand(hookCommand);
|
|
1118
1289
|
program.action(() => {
|
|
1119
1290
|
log.brand();
|
|
1120
1291
|
log.newline();
|
|
@@ -1129,6 +1300,7 @@ program.action(() => {
|
|
|
1129
1300
|
log.plain(" shiva connect Projekte verbinden");
|
|
1130
1301
|
log.plain(" shiva disconnect Verbindung trennen");
|
|
1131
1302
|
log.plain(" shiva config Konfiguration verwalten");
|
|
1303
|
+
log.plain(" shiva hook Claude Code Integration");
|
|
1132
1304
|
log.newline();
|
|
1133
1305
|
log.dim("Hilfe: shiva <befehl> --help");
|
|
1134
1306
|
});
|