custodex 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/detect.d.ts +27 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +108 -0
- package/dist/detect.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +147 -0
- package/dist/index.js.map +1 -0
- package/dist/install.d.ts +59 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +410 -0
- package/dist/install.js.map +1 -0
- package/dist/uninstall.d.ts +11 -0
- package/dist/uninstall.d.ts.map +1 -0
- package/dist/uninstall.js +176 -0
- package/dist/uninstall.js.map +1 -0
- package/dist/wizard.d.ts +20 -0
- package/dist/wizard.d.ts.map +1 -0
- package/dist/wizard.js +332 -0
- package/dist/wizard.js.map +1 -0
- package/hooks/hook.sh +724 -0
- package/package.json +21 -0
- package/plugins/custodex-opencode.ts +330 -0
package/dist/wizard.js
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Wizard
|
|
3
|
+
*
|
|
4
|
+
* Guides the user through detecting installed AI coding tools and wiring
|
|
5
|
+
* Custodex governance hooks into each one. Uses only Node.js built-ins.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from "fs";
|
|
8
|
+
import * as os from "os";
|
|
9
|
+
import * as path from "path";
|
|
10
|
+
import * as readline from "readline";
|
|
11
|
+
import * as https from "https";
|
|
12
|
+
import { detectIDEs } from "./detect.js";
|
|
13
|
+
import { writeSharedConfig, installIDE, registerAdminAgent, } from "./install.js";
|
|
14
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
15
|
+
const VERSION = "1.0.0";
|
|
16
|
+
const DEFAULT_BASE_URL = "https://custodex.vercel.app";
|
|
17
|
+
const CONFIG_PATH = path.join(os.homedir(), ".custodex", "config.json");
|
|
18
|
+
// ─── Terminal helpers ─────────────────────────────────────────────────────────
|
|
19
|
+
const RESET = "\x1b[0m";
|
|
20
|
+
const BOLD = "\x1b[1m";
|
|
21
|
+
const DIM = "\x1b[2m";
|
|
22
|
+
const RED = "\x1b[31m";
|
|
23
|
+
const GREEN = "\x1b[32m";
|
|
24
|
+
const YELLOW = "\x1b[33m";
|
|
25
|
+
const CYAN = "\x1b[36m";
|
|
26
|
+
function print(msg) {
|
|
27
|
+
process.stdout.write(msg + "\n");
|
|
28
|
+
}
|
|
29
|
+
function printBanner() {
|
|
30
|
+
print("");
|
|
31
|
+
print(`${BOLD} CUSTODEX${RESET} — Universal AI Governance`);
|
|
32
|
+
print(`${DIM} v${VERSION}${RESET}`);
|
|
33
|
+
print("");
|
|
34
|
+
}
|
|
35
|
+
function printSeparator() {
|
|
36
|
+
print(" " + "─".repeat(52));
|
|
37
|
+
}
|
|
38
|
+
/** Mask an API key for display: show prefix + redacted middle */
|
|
39
|
+
function maskApiKey(key) {
|
|
40
|
+
if (key.length < 8)
|
|
41
|
+
return "****";
|
|
42
|
+
const prefix = key.slice(0, 4);
|
|
43
|
+
return `${prefix}_${"█".repeat(Math.min(24, key.length - 4))}`;
|
|
44
|
+
}
|
|
45
|
+
// ─── HTTP helper ─────────────────────────────────────────────────────────────
|
|
46
|
+
/** Perform an HTTPS GET and return { status, body }. */
|
|
47
|
+
function httpsGet(url, apiKey) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const parsed = new URL(url);
|
|
50
|
+
const options = {
|
|
51
|
+
hostname: parsed.hostname,
|
|
52
|
+
port: parsed.port || 443,
|
|
53
|
+
path: parsed.pathname + parsed.search,
|
|
54
|
+
method: "GET",
|
|
55
|
+
headers: {
|
|
56
|
+
Authorization: `Bearer ${apiKey}`,
|
|
57
|
+
"User-Agent": `custodex-cli/${VERSION}`,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
const req = https.request(options, (res) => {
|
|
61
|
+
let data = "";
|
|
62
|
+
res.on("data", (chunk) => {
|
|
63
|
+
data += chunk.toString();
|
|
64
|
+
});
|
|
65
|
+
res.on("end", () => resolve({ status: res.statusCode ?? 0, body: data }));
|
|
66
|
+
});
|
|
67
|
+
req.on("error", reject);
|
|
68
|
+
req.setTimeout(8_000, () => req.destroy(new Error("Health check timed out")));
|
|
69
|
+
req.end();
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/** Validate the API key against the backend health endpoint. */
|
|
73
|
+
async function validateApiKey(apiKey, baseUrl) {
|
|
74
|
+
try {
|
|
75
|
+
const result = await httpsGet(`${baseUrl}/api/health`, apiKey);
|
|
76
|
+
return result.status >= 200 && result.status < 300;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// ─── Readline prompt helpers ─────────────────────────────────────────────────
|
|
83
|
+
/** Ask a yes/no question; default determined by `defaultYes`. */
|
|
84
|
+
function askYesNo(rl, question, defaultYes) {
|
|
85
|
+
const hint = defaultYes ? "[Y/n]" : "[y/N]";
|
|
86
|
+
return new Promise((resolve) => {
|
|
87
|
+
rl.question(` ${question} ${hint}: `, (answer) => {
|
|
88
|
+
const trimmed = answer.trim().toLowerCase();
|
|
89
|
+
if (trimmed === "") {
|
|
90
|
+
resolve(defaultYes);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
resolve(trimmed === "y" || trimmed === "yes");
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/** Prompt for a value, optionally masking input. */
|
|
99
|
+
function askInput(rl, question, defaultValue) {
|
|
100
|
+
const hint = defaultValue ? ` (${DIM}${maskApiKey(defaultValue)}${RESET})` : "";
|
|
101
|
+
return new Promise((resolve) => {
|
|
102
|
+
// Mask input by disabling echo
|
|
103
|
+
const input = process.stdin;
|
|
104
|
+
const mute = typeof input.setRawMode === "function";
|
|
105
|
+
rl.question(` ${question}${hint}: `, (answer) => {
|
|
106
|
+
if (mute) {
|
|
107
|
+
process.stdout.write("\n");
|
|
108
|
+
}
|
|
109
|
+
const value = answer.trim() || defaultValue || "";
|
|
110
|
+
resolve(value);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
// ─── Main wizard flow ─────────────────────────────────────────────────────────
|
|
115
|
+
/**
|
|
116
|
+
* Run the interactive installation wizard.
|
|
117
|
+
*/
|
|
118
|
+
export async function runWizard(options = {}) {
|
|
119
|
+
const rl = readline.createInterface({
|
|
120
|
+
input: process.stdin,
|
|
121
|
+
output: process.stdout,
|
|
122
|
+
terminal: true,
|
|
123
|
+
});
|
|
124
|
+
// Ensure readline is closed on exit
|
|
125
|
+
const cleanup = () => {
|
|
126
|
+
rl.close();
|
|
127
|
+
};
|
|
128
|
+
process.on("SIGINT", () => {
|
|
129
|
+
print("\n\n Cancelled.");
|
|
130
|
+
cleanup();
|
|
131
|
+
process.exit(0);
|
|
132
|
+
});
|
|
133
|
+
try {
|
|
134
|
+
printBanner();
|
|
135
|
+
const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
|
|
136
|
+
// ── Step 1: Check for existing config ─────────────────────────────────
|
|
137
|
+
let existingConfig = null;
|
|
138
|
+
if (fs.existsSync(CONFIG_PATH)) {
|
|
139
|
+
try {
|
|
140
|
+
existingConfig = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8"));
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
existingConfig = null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (existingConfig !== null) {
|
|
147
|
+
print(`${YELLOW} Custodex is already configured on this machine.${RESET}`);
|
|
148
|
+
const overwrite = options.autoYes
|
|
149
|
+
? true
|
|
150
|
+
: await askYesNo(rl, "Overwrite existing configuration?", false);
|
|
151
|
+
if (!overwrite) {
|
|
152
|
+
print("\n No changes made.");
|
|
153
|
+
cleanup();
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
print("");
|
|
157
|
+
}
|
|
158
|
+
// ── Step 2: Collect API key ────────────────────────────────────────────
|
|
159
|
+
let apiKey = options.apiKey ?? "";
|
|
160
|
+
if (!apiKey) {
|
|
161
|
+
print(` Enter your Custodex API key.`);
|
|
162
|
+
print(` ${DIM}Get one at ${CYAN}https://custodex.vercel.app/settings/api-keys${RESET}`);
|
|
163
|
+
print("");
|
|
164
|
+
apiKey = await askInput(rl, "API key");
|
|
165
|
+
}
|
|
166
|
+
// Validate format
|
|
167
|
+
if (!apiKey.startsWith("cus_") || apiKey.length < 36) {
|
|
168
|
+
print(`\n${RED} Invalid API key format.${RESET} Keys must start with "cus_" and be at least 36 characters.`);
|
|
169
|
+
cleanup();
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
print(`\n Key: ${DIM}${maskApiKey(apiKey)}${RESET}`);
|
|
173
|
+
print("");
|
|
174
|
+
// ── Step 3: Validate key against backend ──────────────────────────────
|
|
175
|
+
process.stdout.write(" Validating API key... ");
|
|
176
|
+
const valid = await validateApiKey(apiKey, baseUrl);
|
|
177
|
+
if (!valid) {
|
|
178
|
+
process.stdout.write(`${RED}FAILED${RESET}\n`);
|
|
179
|
+
print(`\n${RED} Could not reach Custodex. Check your API key and try again.${RESET}`);
|
|
180
|
+
cleanup();
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
process.stdout.write(`${GREEN}OK${RESET}\n`);
|
|
184
|
+
print("");
|
|
185
|
+
// ── Step 4: Detect IDEs ───────────────────────────────────────────────
|
|
186
|
+
printSeparator();
|
|
187
|
+
print(` ${BOLD}Detecting AI coding tools${RESET}`);
|
|
188
|
+
printSeparator();
|
|
189
|
+
print("");
|
|
190
|
+
const allIDEs = detectIDEs();
|
|
191
|
+
const detectedIDEs = [];
|
|
192
|
+
for (const ide of allIDEs) {
|
|
193
|
+
if (ide.detected) {
|
|
194
|
+
const ver = ide.version ? ` ${DIM}(${ide.version})${RESET}` : "";
|
|
195
|
+
print(` ${GREEN}✓${RESET} ${BOLD}${ide.name}${RESET}${ver}`);
|
|
196
|
+
detectedIDEs.push(ide);
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
print(` ${DIM} ${ide.name} — not found${RESET}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
print("");
|
|
203
|
+
if (detectedIDEs.length === 0) {
|
|
204
|
+
print(`${YELLOW} No AI coding tools detected.${RESET} Nothing to govern.`);
|
|
205
|
+
print(` Install Claude Code, Cursor, Gemini CLI, or OpenCode and re-run.`);
|
|
206
|
+
cleanup();
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
// ── Step 5: Confirm ───────────────────────────────────────────────────
|
|
210
|
+
printSeparator();
|
|
211
|
+
print(` ${BOLD}Install governance hooks${RESET} into ${detectedIDEs.length} tool${detectedIDEs.length === 1 ? "" : "s"}?`);
|
|
212
|
+
printSeparator();
|
|
213
|
+
print("");
|
|
214
|
+
const confirmed = options.autoYes
|
|
215
|
+
? true
|
|
216
|
+
: await askYesNo(rl, "Proceed with installation?", true);
|
|
217
|
+
if (!confirmed) {
|
|
218
|
+
print("\n Installation cancelled. No changes made.");
|
|
219
|
+
cleanup();
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
print("");
|
|
223
|
+
// ── Step 6: Write shared config + hook script ─────────────────────────
|
|
224
|
+
process.stdout.write(" Writing shared config... ");
|
|
225
|
+
try {
|
|
226
|
+
writeSharedConfig({
|
|
227
|
+
apiKey,
|
|
228
|
+
baseUrl,
|
|
229
|
+
version: VERSION,
|
|
230
|
+
installedAt: Date.now(),
|
|
231
|
+
});
|
|
232
|
+
process.stdout.write(`${GREEN}OK${RESET}\n`);
|
|
233
|
+
}
|
|
234
|
+
catch (err) {
|
|
235
|
+
process.stdout.write(`${RED}FAILED${RESET}\n`);
|
|
236
|
+
print(`${RED} ${String(err)}${RESET}`);
|
|
237
|
+
cleanup();
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
// ── Step 7: Install per-IDE ───────────────────────────────────────────
|
|
241
|
+
printSeparator();
|
|
242
|
+
print(` ${BOLD}Installing hooks${RESET}`);
|
|
243
|
+
printSeparator();
|
|
244
|
+
print("");
|
|
245
|
+
const results = [];
|
|
246
|
+
for (const ide of detectedIDEs) {
|
|
247
|
+
process.stdout.write(` ${ide.name}... `);
|
|
248
|
+
const result = installIDE(ide);
|
|
249
|
+
results.push(result);
|
|
250
|
+
if (result.success) {
|
|
251
|
+
process.stdout.write(`${GREEN}OK${RESET}\n`);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
process.stdout.write(`${RED}FAILED${RESET}\n`);
|
|
255
|
+
print(` ${DIM}${result.error ?? "Unknown error"}${RESET}`);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
print("");
|
|
259
|
+
// ── Step 8: Register admin agent ──────────────────────────────────────
|
|
260
|
+
process.stdout.write(" Registering admin agent... ");
|
|
261
|
+
const agent = await registerAdminAgent(apiKey, baseUrl);
|
|
262
|
+
if (agent) {
|
|
263
|
+
process.stdout.write(`${GREEN}OK${RESET}\n`);
|
|
264
|
+
print(` ${DIM}Agent ID: ${agent.agentId}${RESET}`);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
process.stdout.write(`${YELLOW}SKIPPED${RESET}\n`);
|
|
268
|
+
print(` ${DIM}Could not register admin agent — governance hooks are still active.${RESET}`);
|
|
269
|
+
}
|
|
270
|
+
print("");
|
|
271
|
+
// ── Step 9: Summary ───────────────────────────────────────────────────
|
|
272
|
+
printSeparator();
|
|
273
|
+
const successCount = results.filter((r) => r.success).length;
|
|
274
|
+
print(` ${GREEN}${BOLD}Custodex is now active.${RESET} ` +
|
|
275
|
+
`${successCount}/${results.length} tool${results.length === 1 ? "" : "s"} governed.`);
|
|
276
|
+
printSeparator();
|
|
277
|
+
print("");
|
|
278
|
+
print(` ${YELLOW}Restart your IDEs${RESET} to activate governance hooks.`);
|
|
279
|
+
print(` ${DIM}Dashboard: ${CYAN}${baseUrl}${RESET}`);
|
|
280
|
+
print("");
|
|
281
|
+
}
|
|
282
|
+
finally {
|
|
283
|
+
cleanup();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// ─── Status command ───────────────────────────────────────────────────────────
|
|
287
|
+
/**
|
|
288
|
+
* Print the current Custodex configuration status without modifying anything.
|
|
289
|
+
*/
|
|
290
|
+
export function runStatus() {
|
|
291
|
+
printBanner();
|
|
292
|
+
if (!fs.existsSync(CONFIG_PATH)) {
|
|
293
|
+
print(` ${YELLOW}Not configured.${RESET} Run ${BOLD}npx custodex init${RESET} to get started.`);
|
|
294
|
+
print("");
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
let config = {};
|
|
298
|
+
try {
|
|
299
|
+
config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf8"));
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
print(` ${RED}Config file is corrupted.${RESET} Re-run ${BOLD}npx custodex init${RESET}.`);
|
|
303
|
+
print("");
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
print(` ${GREEN}Custodex is configured.${RESET}`);
|
|
307
|
+
print("");
|
|
308
|
+
const apiKey = typeof config["apiKey"] === "string" ? config["apiKey"] : "";
|
|
309
|
+
const baseUrl = typeof config["baseUrl"] === "string" ? config["baseUrl"] : DEFAULT_BASE_URL;
|
|
310
|
+
const installedAt = typeof config["installedAt"] === "number"
|
|
311
|
+
? new Date(config["installedAt"]).toLocaleString()
|
|
312
|
+
: "unknown";
|
|
313
|
+
print(` API key: ${DIM}${maskApiKey(apiKey)}${RESET}`);
|
|
314
|
+
print(` Base URL: ${DIM}${baseUrl}${RESET}`);
|
|
315
|
+
print(` Installed: ${DIM}${installedAt}${RESET}`);
|
|
316
|
+
print(` Config: ${DIM}${CONFIG_PATH}${RESET}`);
|
|
317
|
+
print("");
|
|
318
|
+
// Show per-IDE status
|
|
319
|
+
printSeparator();
|
|
320
|
+
print(` ${BOLD}Detected tools${RESET}`);
|
|
321
|
+
printSeparator();
|
|
322
|
+
print("");
|
|
323
|
+
const ides = detectIDEs();
|
|
324
|
+
for (const ide of ides) {
|
|
325
|
+
const status = ide.detected ? `${GREEN}detected${RESET}` : `${DIM}not found${RESET}`;
|
|
326
|
+
const ver = ide.version ? ` ${DIM}${ide.version}${RESET}` : "";
|
|
327
|
+
print(` ${BOLD}${ide.name}${RESET} ${status}${ver}`);
|
|
328
|
+
print(` ${DIM}${ide.globalConfigPath}${RESET}`);
|
|
329
|
+
print("");
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=wizard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wizard.js","sourceRoot":"","sources":["../src/wizard.ts"],"names":[],"mappings":"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"}
|