claudeos-core 1.0.7 → 1.2.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.
Potentially problematic release.
This version of claudeos-core might be problematic. Click here for more details.
- package/CHANGELOG.md +84 -1
- package/CONTRIBUTING.md +15 -4
- package/README.de.md +187 -11
- package/README.es.md +187 -11
- package/README.fr.md +187 -11
- package/README.hi.md +187 -11
- package/README.ja.md +186 -10
- package/README.ko.md +331 -364
- package/README.md +200 -11
- package/README.ru.md +187 -11
- package/README.vi.md +188 -12
- package/README.zh-CN.md +186 -10
- package/bin/cli.js +183 -61
- package/bootstrap.sh +128 -21
- package/content-validator/index.js +131 -60
- package/health-checker/index.js +29 -23
- package/import-linter/index.js +14 -8
- package/manifest-generator/index.js +26 -20
- package/package.json +84 -75
- package/pass-json-validator/index.js +92 -70
- package/pass-prompts/templates/common/header.md +4 -4
- package/pass-prompts/templates/common/lang-instructions.json +27 -0
- package/pass-prompts/templates/common/pass3-footer.md +2 -3
- package/pass-prompts/templates/java-spring/pass1.md +84 -81
- package/pass-prompts/templates/java-spring/pass2.md +66 -66
- package/pass-prompts/templates/java-spring/pass3.md +60 -60
- package/pass-prompts/templates/kotlin-spring/pass1.md +172 -0
- package/pass-prompts/templates/kotlin-spring/pass2.md +109 -0
- package/pass-prompts/templates/kotlin-spring/pass3.md +98 -0
- package/pass-prompts/templates/node-express/pass1.md +73 -73
- package/pass-prompts/templates/node-express/pass2.md +66 -66
- package/pass-prompts/templates/node-express/pass3.md +53 -53
- package/pass-prompts/templates/node-nextjs/pass1.md +68 -68
- package/pass-prompts/templates/node-nextjs/pass2.md +61 -61
- package/pass-prompts/templates/node-nextjs/pass3.md +48 -48
- package/pass-prompts/templates/python-django/pass1.md +78 -78
- package/pass-prompts/templates/python-django/pass2.md +69 -69
- package/pass-prompts/templates/python-django/pass3.md +45 -45
- package/pass-prompts/templates/python-fastapi/pass1.md +76 -76
- package/pass-prompts/templates/python-fastapi/pass2.md +67 -67
- package/pass-prompts/templates/python-fastapi/pass3.md +45 -45
- package/plan-installer/index.js +623 -97
- package/plan-validator/index.js +54 -23
- package/sync-checker/index.js +25 -14
package/bin/cli.js
CHANGED
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Node.js replacement for bootstrap.sh with cross-platform support.
|
|
7
7
|
* Usage:
|
|
8
|
-
* npx claudeos-core init
|
|
9
|
-
* npx claudeos-core
|
|
10
|
-
* npx claudeos-core
|
|
11
|
-
* npx claudeos-core
|
|
12
|
-
* npx claudeos-core
|
|
13
|
-
* npx claudeos-core
|
|
8
|
+
* npx claudeos-core init --lang ko ← Run 3-Pass pipeline (Korean output)
|
|
9
|
+
* npx claudeos-core init ← Interactive language selection
|
|
10
|
+
* npx claudeos-core health ← Run health checker
|
|
11
|
+
* npx claudeos-core validate ← Run plan validator (--check)
|
|
12
|
+
* npx claudeos-core restore ← Restore from Master Plan
|
|
13
|
+
* npx claudeos-core refresh ← Sync disk → Plan
|
|
14
|
+
* npx claudeos-core --help ← Show help
|
|
14
15
|
*
|
|
15
16
|
* Also works when cloned directly:
|
|
16
17
|
* node claudeos-core-tools/bin/cli.js init
|
|
@@ -20,16 +21,75 @@ const { execSync } = require("child_process");
|
|
|
20
21
|
const fs = require("fs");
|
|
21
22
|
const path = require("path");
|
|
22
23
|
|
|
23
|
-
// ───
|
|
24
|
+
// ─── Path configuration ──────────────────────────────────────────
|
|
24
25
|
const TOOLS_DIR = path.resolve(__dirname, "..");
|
|
25
26
|
const PROJECT_ROOT = process.cwd();
|
|
26
27
|
const GENERATED_DIR = path.join(PROJECT_ROOT, "claudeos-core/generated");
|
|
27
28
|
|
|
28
|
-
//
|
|
29
|
-
// (
|
|
29
|
+
// Set env var so sub-tools (plan-installer, etc.) correctly resolve the project root
|
|
30
|
+
// (Required because __dirname-based calculation is incorrect when run via npm/npx)
|
|
30
31
|
process.env.CLAUDEOS_ROOT = PROJECT_ROOT;
|
|
31
32
|
|
|
32
|
-
// ───
|
|
33
|
+
// ─── Language configuration ──────────────────────────────────────
|
|
34
|
+
const SUPPORTED_LANGS = {
|
|
35
|
+
en: "English",
|
|
36
|
+
ko: "한국어 (Korean)",
|
|
37
|
+
"zh-CN": "简体中文 (Chinese Simplified)",
|
|
38
|
+
ja: "日本語 (Japanese)",
|
|
39
|
+
es: "Español (Spanish)",
|
|
40
|
+
vi: "Tiếng Việt (Vietnamese)",
|
|
41
|
+
hi: "हिन्दी (Hindi)",
|
|
42
|
+
ru: "Русский (Russian)",
|
|
43
|
+
fr: "Français (French)",
|
|
44
|
+
de: "Deutsch (German)",
|
|
45
|
+
};
|
|
46
|
+
const LANG_CODES = Object.keys(SUPPORTED_LANGS);
|
|
47
|
+
|
|
48
|
+
function isValidLang(lang) {
|
|
49
|
+
return LANG_CODES.includes(lang);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Interactive language selection (stdin prompt)
|
|
53
|
+
function selectLangInteractive() {
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
const readline = require("readline");
|
|
56
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
57
|
+
|
|
58
|
+
log("");
|
|
59
|
+
log("╔══════════════════════════════════════════════════╗");
|
|
60
|
+
log("║ Select output language (required) ║");
|
|
61
|
+
log("╚══════════════════════════════════════════════════╝");
|
|
62
|
+
log("");
|
|
63
|
+
LANG_CODES.forEach((code, i) => {
|
|
64
|
+
log(` ${String(i + 1).padStart(2)}. ${code.padEnd(6)} — ${SUPPORTED_LANGS[code]}`);
|
|
65
|
+
});
|
|
66
|
+
log("");
|
|
67
|
+
|
|
68
|
+
rl.question(` Enter number (1-${LANG_CODES.length}) or language code: `, (answer) => {
|
|
69
|
+
rl.close();
|
|
70
|
+
const trimmed = answer.trim();
|
|
71
|
+
|
|
72
|
+
// Accept number
|
|
73
|
+
const num = parseInt(trimmed);
|
|
74
|
+
if (num >= 1 && num <= LANG_CODES.length) {
|
|
75
|
+
resolve(LANG_CODES[num - 1]);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Accept language code
|
|
80
|
+
if (isValidLang(trimmed)) {
|
|
81
|
+
resolve(trimmed);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
log(`\n ❌ Invalid selection: "${trimmed}"`);
|
|
86
|
+
log(` Supported: ${LANG_CODES.join(", ")}\n`);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ─── Utilities ───────────────────────────────────────────
|
|
33
93
|
function log(msg) {
|
|
34
94
|
console.log(msg);
|
|
35
95
|
}
|
|
@@ -46,6 +106,7 @@ function run(cmd, options = {}) {
|
|
|
46
106
|
cwd: options.cwd || PROJECT_ROOT,
|
|
47
107
|
stdio: options.silent ? ["pipe", "pipe", "pipe"] : "inherit",
|
|
48
108
|
encoding: "utf-8",
|
|
109
|
+
timeout: options.timeout || 0, // no timeout (Pass 1-3 can take 10+ minutes)
|
|
49
110
|
});
|
|
50
111
|
return true;
|
|
51
112
|
} catch (e) {
|
|
@@ -54,26 +115,20 @@ function run(cmd, options = {}) {
|
|
|
54
115
|
}
|
|
55
116
|
}
|
|
56
117
|
|
|
57
|
-
// claude -p
|
|
118
|
+
// Run claude -p: pass prompt via stdin (no shell pipe — avoids command injection)
|
|
58
119
|
function runClaudePrompt(prompt, options = {}) {
|
|
59
|
-
const tmpFile = path.join(GENERATED_DIR, "_tmp_prompt.md");
|
|
60
|
-
fs.writeFileSync(tmpFile, prompt, "utf-8");
|
|
61
120
|
try {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const cmd = `${catCmd} ${escaped} | claude -p --dangerously-skip-permissions`;
|
|
65
|
-
execSync(cmd, {
|
|
121
|
+
execSync("claude -p --dangerously-skip-permissions", {
|
|
122
|
+
input: prompt,
|
|
66
123
|
cwd: options.cwd || PROJECT_ROOT,
|
|
67
|
-
stdio: "inherit",
|
|
124
|
+
stdio: ["pipe", "inherit", "inherit"],
|
|
68
125
|
encoding: "utf-8",
|
|
69
|
-
|
|
126
|
+
timeout: 0, // no timeout (Claude analysis can be long-running)
|
|
70
127
|
});
|
|
71
128
|
return true;
|
|
72
129
|
} catch (e) {
|
|
73
130
|
if (options.ignoreError) return false;
|
|
74
131
|
throw e;
|
|
75
|
-
} finally {
|
|
76
|
-
try { fs.unlinkSync(tmpFile); } catch {}
|
|
77
132
|
}
|
|
78
133
|
}
|
|
79
134
|
|
|
@@ -95,9 +150,19 @@ function injectProjectRoot(text) {
|
|
|
95
150
|
return text.replace(/\{\{PROJECT_ROOT\}\}/g, PROJECT_ROOT);
|
|
96
151
|
}
|
|
97
152
|
|
|
98
|
-
// ───
|
|
153
|
+
// ─── Command: init ───────────────────────────────────────
|
|
99
154
|
async function cmdInit() {
|
|
100
|
-
// ───
|
|
155
|
+
// ─── Prerequisites check ───────────────────────────────────
|
|
156
|
+
// Validate PROJECT_ROOT is a plausible project directory
|
|
157
|
+
const hasProjectMarker = [".git", "package.json", "build.gradle", "build.gradle.kts", "pom.xml", "pyproject.toml", "requirements.txt"].some(
|
|
158
|
+
m => fs.existsSync(path.join(PROJECT_ROOT, m))
|
|
159
|
+
);
|
|
160
|
+
if (!hasProjectMarker) {
|
|
161
|
+
log(`\n ⚠️ Warning: ${PROJECT_ROOT} does not look like a project root.`);
|
|
162
|
+
log(" No .git, package.json, build.gradle, or pom.xml found.");
|
|
163
|
+
log(" Run this command from your project directory.\n");
|
|
164
|
+
}
|
|
165
|
+
|
|
101
166
|
const nodeVersion = parseInt(process.versions.node.split(".")[0]);
|
|
102
167
|
if (nodeVersion < 18) {
|
|
103
168
|
log(`\n ❌ Node.js v18+ required (current: v${process.versions.node})`);
|
|
@@ -113,21 +178,44 @@ async function cmdInit() {
|
|
|
113
178
|
process.exit(1);
|
|
114
179
|
}
|
|
115
180
|
|
|
181
|
+
// Verify Claude is authenticated (quick prompt test)
|
|
182
|
+
const claudeAuth = run('claude -p "echo ok" --max-tokens 10', { silent: true, ignoreError: true });
|
|
183
|
+
if (!claudeAuth) {
|
|
184
|
+
log("\n ⚠️ Claude Code may not be authenticated.");
|
|
185
|
+
log(" Run: claude (and complete authentication)");
|
|
186
|
+
log(" Then retry: npx claudeos-core init\n");
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ─── Language selection (required) ────────────────────────────
|
|
191
|
+
let lang = parsedArgs.lang;
|
|
192
|
+
if (!lang) {
|
|
193
|
+
// Interactive selection if --lang not provided
|
|
194
|
+
lang = await selectLangInteractive();
|
|
195
|
+
}
|
|
196
|
+
if (!isValidLang(lang)) {
|
|
197
|
+
log(`\n ❌ Unsupported language: "${lang}"`);
|
|
198
|
+
log(` Supported: ${LANG_CODES.join(", ")}\n`);
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
process.env.CLAUDEOS_LANG = lang;
|
|
202
|
+
|
|
116
203
|
log("");
|
|
117
204
|
log("╔════════════════════════════════════════════════════╗");
|
|
118
205
|
log("║ ClaudeOS-Core — Bootstrap (3-Pass) ║");
|
|
119
206
|
log("╚════════════════════════════════════════════════════╝");
|
|
120
207
|
log(` Project root: ${PROJECT_ROOT}`);
|
|
208
|
+
log(` Language: ${SUPPORTED_LANGS[lang]} (${lang})`);
|
|
121
209
|
log("");
|
|
122
210
|
|
|
123
|
-
// ─── [1]
|
|
211
|
+
// ─── [1] Install dependencies ────────────────────────────────
|
|
124
212
|
header("[1] Installing dependencies...");
|
|
125
213
|
if (!fileExists(path.join(TOOLS_DIR, "node_modules"))) {
|
|
126
214
|
run("npm install --silent", { cwd: TOOLS_DIR });
|
|
127
215
|
}
|
|
128
216
|
log(" ✅ Done\n");
|
|
129
217
|
|
|
130
|
-
// ─── [2]
|
|
218
|
+
// ─── [2] Create directory structure ─────────────────────────
|
|
131
219
|
header("[2] Creating directory structure...");
|
|
132
220
|
const dirs = [
|
|
133
221
|
".claude/rules/00.core",
|
|
@@ -162,20 +250,27 @@ async function cmdInit() {
|
|
|
162
250
|
}
|
|
163
251
|
log(" ✅ Done\n");
|
|
164
252
|
|
|
165
|
-
// ─── [3] plan-installer
|
|
253
|
+
// ─── [3] Run plan-installer ─────────────────────────
|
|
166
254
|
header("[3] Analyzing project (plan-installer)...");
|
|
167
255
|
run(`node "${path.join(TOOLS_DIR, "plan-installer/index.js")}"`);
|
|
168
256
|
log("");
|
|
169
257
|
|
|
170
|
-
// ─── [4] Pass 1:
|
|
258
|
+
// ─── [4] Pass 1: Deep analysis per domain group ──────────────────
|
|
171
259
|
header("[4] Pass 1 — Deep analysis per domain group...");
|
|
172
260
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
261
|
+
let domainGroups;
|
|
262
|
+
try {
|
|
263
|
+
domainGroups = JSON.parse(
|
|
264
|
+
readFile(path.join(GENERATED_DIR, "domain-groups.json"))
|
|
265
|
+
);
|
|
266
|
+
} catch (e) {
|
|
267
|
+
log(` ❌ domain-groups.json is missing or malformed: ${e.message}`);
|
|
268
|
+
log(" Re-run plan-installer or check claudeos-core/generated/");
|
|
269
|
+
process.exit(1);
|
|
270
|
+
}
|
|
176
271
|
const totalGroups = domainGroups.totalGroups;
|
|
177
272
|
|
|
178
|
-
//
|
|
273
|
+
// Load pass1 prompts by type
|
|
179
274
|
const pass1Prompts = {};
|
|
180
275
|
for (const type of ["backend", "frontend"]) {
|
|
181
276
|
const promptFile = path.join(GENERATED_DIR, `pass1-${type}-prompt.md`);
|
|
@@ -183,12 +278,16 @@ async function cmdInit() {
|
|
|
183
278
|
pass1Prompts[type] = readFile(promptFile);
|
|
184
279
|
}
|
|
185
280
|
}
|
|
186
|
-
//
|
|
281
|
+
// Single-stack backward compatibility
|
|
187
282
|
if (Object.keys(pass1Prompts).length === 0) {
|
|
188
283
|
const fallback = path.join(GENERATED_DIR, "pass1-prompt.md");
|
|
189
284
|
if (fileExists(fallback)) pass1Prompts["backend"] = readFile(fallback);
|
|
190
285
|
}
|
|
191
286
|
|
|
287
|
+
if (!domainGroups.groups || totalGroups !== domainGroups.groups.length) {
|
|
288
|
+
log(` ❌ domain-groups.json is malformed: expected ${totalGroups} groups, found ${domainGroups.groups ? domainGroups.groups.length : 0}`);
|
|
289
|
+
process.exit(1);
|
|
290
|
+
}
|
|
192
291
|
for (let i = 1; i <= totalGroups; i++) {
|
|
193
292
|
const group = domainGroups.groups[i - 1];
|
|
194
293
|
const domainList = group.domains.join(", ");
|
|
@@ -207,14 +306,14 @@ async function cmdInit() {
|
|
|
207
306
|
continue;
|
|
208
307
|
}
|
|
209
308
|
|
|
210
|
-
//
|
|
309
|
+
// Select prompt for this type
|
|
211
310
|
const template = pass1Prompts[groupType] || pass1Prompts["backend"];
|
|
212
311
|
if (!template) {
|
|
213
312
|
log(` ❌ No pass1 prompt found for type: ${groupType}. Aborting.`);
|
|
214
313
|
process.exit(1);
|
|
215
314
|
}
|
|
216
315
|
|
|
217
|
-
//
|
|
316
|
+
// Placeholder substitution
|
|
218
317
|
let prompt = template
|
|
219
318
|
.replace(/\{\{DOMAIN_GROUP\}\}/g, domainList)
|
|
220
319
|
.replace(/\{\{PASS_NUM\}\}/g, String(i));
|
|
@@ -236,7 +335,7 @@ async function cmdInit() {
|
|
|
236
335
|
}
|
|
237
336
|
log("");
|
|
238
337
|
|
|
239
|
-
// ─── [5] Pass 2:
|
|
338
|
+
// ─── [5] Pass 2: Merge analysis results ──────────────────────
|
|
240
339
|
header("[5] Pass 2 — Merging analysis results...");
|
|
241
340
|
|
|
242
341
|
const pass2Json = path.join(GENERATED_DIR, "pass2-merged.json");
|
|
@@ -263,7 +362,7 @@ async function cmdInit() {
|
|
|
263
362
|
}
|
|
264
363
|
log("");
|
|
265
364
|
|
|
266
|
-
// ─── [6] Pass 3:
|
|
365
|
+
// ─── [6] Pass 3: Generate + verify ─────────────────────────
|
|
267
366
|
header("[6] Pass 3 — Generating all files...");
|
|
268
367
|
|
|
269
368
|
let prompt = injectProjectRoot(
|
|
@@ -283,7 +382,7 @@ async function cmdInit() {
|
|
|
283
382
|
}
|
|
284
383
|
log("");
|
|
285
384
|
|
|
286
|
-
// ─── [7]
|
|
385
|
+
// ─── [7] Run verification tools ───────────────────────────────
|
|
287
386
|
header("[7] Running verification tools...");
|
|
288
387
|
|
|
289
388
|
const verifyTools = [
|
|
@@ -303,7 +402,7 @@ async function cmdInit() {
|
|
|
303
402
|
}
|
|
304
403
|
log("");
|
|
305
404
|
|
|
306
|
-
// ───
|
|
405
|
+
// ─── Complete ─────────────────────────────────────────────
|
|
307
406
|
const totalFiles = countFiles();
|
|
308
407
|
const pass1Files = countPass1Files();
|
|
309
408
|
|
|
@@ -314,6 +413,7 @@ async function cmdInit() {
|
|
|
314
413
|
log(`║ Files created: ${pad(String(totalFiles), 29)}║`);
|
|
315
414
|
log(`║ Domains analyzed: ${pad(totalGroups + " groups", 29)}║`);
|
|
316
415
|
log(`║ Analysis passes: ${pad(pass1Files + " pass1 files", 29)}║`);
|
|
416
|
+
log(`║ Output language: ${pad(SUPPORTED_LANGS[lang] || lang, 29)}║`);
|
|
317
417
|
log("║ ║");
|
|
318
418
|
log("║ Verify anytime: ║");
|
|
319
419
|
log("║ npx claudeos-core health ║");
|
|
@@ -324,35 +424,27 @@ async function cmdInit() {
|
|
|
324
424
|
log("");
|
|
325
425
|
}
|
|
326
426
|
|
|
327
|
-
// ───
|
|
427
|
+
// ─── Command: health ─────────────────────────────────────
|
|
328
428
|
function cmdHealth() {
|
|
329
429
|
run(`node "${path.join(TOOLS_DIR, "health-checker/index.js")}"`);
|
|
330
430
|
}
|
|
331
431
|
|
|
332
|
-
// ───
|
|
432
|
+
// ─── Command: validate ───────────────────────────────────
|
|
333
433
|
function cmdValidate() {
|
|
334
434
|
run(`node "${path.join(TOOLS_DIR, "plan-validator/index.js")}" --check`);
|
|
335
435
|
}
|
|
336
436
|
|
|
337
|
-
// ───
|
|
437
|
+
// ─── Command: restore ────────────────────────────────────
|
|
338
438
|
function cmdRestore() {
|
|
339
439
|
run(`node "${path.join(TOOLS_DIR, "plan-validator/index.js")}" --execute`);
|
|
340
440
|
}
|
|
341
441
|
|
|
342
|
-
// ───
|
|
442
|
+
// ─── Command: refresh ────────────────────────────────────
|
|
343
443
|
function cmdRefresh() {
|
|
344
444
|
run(`node "${path.join(TOOLS_DIR, "plan-validator/index.js")}" --refresh`);
|
|
345
445
|
}
|
|
346
446
|
|
|
347
|
-
// ───
|
|
348
|
-
function escapeShellArg(arg) {
|
|
349
|
-
// Cross-platform shell argument escaping
|
|
350
|
-
if (process.platform === "win32") {
|
|
351
|
-
return `"${arg.replace(/"/g, '\\"')}"`;
|
|
352
|
-
}
|
|
353
|
-
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
354
|
-
}
|
|
355
|
-
|
|
447
|
+
// ─── Helpers ───────────────────────────────────────────────
|
|
356
448
|
function pad(str, len) {
|
|
357
449
|
return str.length >= len ? str : str + " ".repeat(len - str.length);
|
|
358
450
|
}
|
|
@@ -360,10 +452,11 @@ function pad(str, len) {
|
|
|
360
452
|
function countFiles() {
|
|
361
453
|
try {
|
|
362
454
|
let count = 0;
|
|
455
|
+
const skipDirs = ["node_modules", "generated"];
|
|
363
456
|
const scan = (dir) => {
|
|
364
457
|
if (!fs.existsSync(dir)) return;
|
|
365
458
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
366
|
-
if (entry.name
|
|
459
|
+
if (skipDirs.includes(entry.name)) continue;
|
|
367
460
|
const full = path.join(dir, entry.name);
|
|
368
461
|
if (entry.isDirectory()) scan(full);
|
|
369
462
|
else count++;
|
|
@@ -403,19 +496,44 @@ Commands:
|
|
|
403
496
|
restore Restore all files from Master Plan
|
|
404
497
|
|
|
405
498
|
Options:
|
|
499
|
+
--lang CODE Output language for generated files (required for init)
|
|
500
|
+
Supported: en, ko, zh-CN, ja, es, vi, hi, ru, fr, de
|
|
501
|
+
If omitted, interactive selection is shown.
|
|
406
502
|
--help Show this help message
|
|
407
503
|
--version Show version
|
|
408
504
|
|
|
409
505
|
Examples:
|
|
410
|
-
npx claudeos-core init
|
|
411
|
-
npx claudeos-core
|
|
412
|
-
npx claudeos-core
|
|
506
|
+
npx claudeos-core init --lang ko # Generate in Korean
|
|
507
|
+
npx claudeos-core init --lang ja # Generate in Japanese
|
|
508
|
+
npx claudeos-core init # Interactive language selection
|
|
509
|
+
npx claudeos-core health # Check everything is consistent
|
|
510
|
+
npx claudeos-core restore # Recover from corrupted docs
|
|
413
511
|
`);
|
|
414
512
|
}
|
|
415
513
|
|
|
416
|
-
// ───
|
|
514
|
+
// ─── Argument parser ────────────────────────────────────────
|
|
515
|
+
function parseArgs(argv) {
|
|
516
|
+
const result = { command: null, lang: null };
|
|
517
|
+
for (let i = 0; i < argv.length; i++) {
|
|
518
|
+
if (argv[i] === "--lang" && i + 1 < argv.length) {
|
|
519
|
+
result.lang = argv[++i];
|
|
520
|
+
} else if (argv[i].startsWith("--lang=")) {
|
|
521
|
+
result.lang = argv[i].split("=")[1];
|
|
522
|
+
} else if (argv[i] === "--help" || argv[i] === "-h") {
|
|
523
|
+
result.command = "--help";
|
|
524
|
+
} else if (argv[i] === "--version" || argv[i] === "-v") {
|
|
525
|
+
result.command = "--version";
|
|
526
|
+
} else if (!argv[i].startsWith("-") && !result.command) {
|
|
527
|
+
result.command = argv[i];
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
return result;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// ─── Main ───────────────────────────────────────────────
|
|
417
534
|
const args = process.argv.slice(2);
|
|
418
|
-
const
|
|
535
|
+
const parsedArgs = parseArgs(args);
|
|
536
|
+
const command = parsedArgs.command;
|
|
419
537
|
|
|
420
538
|
if (!command || command === "--help" || command === "-h") {
|
|
421
539
|
showHelp();
|
|
@@ -423,10 +541,14 @@ if (!command || command === "--help" || command === "-h") {
|
|
|
423
541
|
}
|
|
424
542
|
|
|
425
543
|
if (command === "--version" || command === "-v") {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
544
|
+
try {
|
|
545
|
+
const pkg = JSON.parse(
|
|
546
|
+
readFile(path.join(TOOLS_DIR, "package.json"))
|
|
547
|
+
);
|
|
548
|
+
log(`claudeos-core v${pkg.version}`);
|
|
549
|
+
} catch {
|
|
550
|
+
log("claudeos-core (version unknown)");
|
|
551
|
+
}
|
|
430
552
|
process.exit(0);
|
|
431
553
|
}
|
|
432
554
|
|