skillwiki 0.2.0-beta.3 → 0.2.0-beta.4

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.
Files changed (2) hide show
  1. package/dist/cli.js +277 -25
  2. package/package.json +13 -4
package/dist/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli.ts
4
+ import { readFileSync } from "fs";
4
5
  import { Command } from "commander";
5
6
 
6
7
  // src/utils/output.ts
@@ -9,9 +10,14 @@ function printJson(r) {
9
10
  }
10
11
  function printHuman(r) {
11
12
  if (r.ok) {
12
- process.stdout.write(`OK
13
+ if (typeof r.data === "object" && r.data !== null && "humanHint" in r.data) {
14
+ process.stdout.write(`${r.data.humanHint}
15
+ `);
16
+ } else {
17
+ process.stdout.write(`OK
13
18
  ${formatData(r.data)}
14
19
  `);
20
+ }
15
21
  } else {
16
22
  process.stdout.write(`ERR ${r.error}
17
23
  ${r.detail !== void 0 ? formatData(r.detail) + "\n" : ""}`);
@@ -53,15 +59,19 @@ var ExitCode = {
53
59
  LINT_HAS_WARNINGS: 22,
54
60
  LINT_HAS_ERRORS: 23,
55
61
  ENV_WRITE_CONFLICT: 24,
56
- NO_VAULT_CONFIGURED: 25
62
+ NO_VAULT_CONFIGURED: 25,
63
+ INVALID_CONFIG_KEY: 26,
64
+ CONFIG_WRITE_FAILED: 27,
65
+ DOCTOR_HAS_WARNINGS: 28,
66
+ DOCTOR_HAS_ERRORS: 29
57
67
  };
58
68
 
59
69
  // ../shared/src/json-output.ts
60
70
  function ok(data) {
61
71
  return { ok: true, data };
62
72
  }
63
- function err(error, detail) {
64
- return detail === void 0 ? { ok: false, error } : { ok: false, error, detail };
73
+ function err(error2, detail) {
74
+ return detail === void 0 ? { ok: false, error: error2 } : { ok: false, error: error2, detail };
65
75
  }
66
76
 
67
77
  // ../shared/src/schemas.ts
@@ -479,7 +489,8 @@ async function runOverlap(input) {
479
489
  import { join as join2 } from "path";
480
490
 
481
491
  // src/utils/dotenv.ts
482
- import { readFile as readFile4 } from "fs/promises";
492
+ import { readFile as readFile4, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
493
+ import { dirname as dirname2 } from "path";
483
494
  var WHITELIST = /* @__PURE__ */ new Set(["WIKI_PATH", "WIKI_LANG"]);
484
495
  async function parseDotenvFile(path) {
485
496
  let text;
@@ -502,6 +513,50 @@ async function parseDotenvFile(path) {
502
513
  }
503
514
  return out;
504
515
  }
516
+ async function writeDotenv(filePath, entries, originalContent) {
517
+ const lines = originalContent !== void 0 ? updateLines(originalContent, entries) : freshLines(entries);
518
+ await mkdir2(dirname2(filePath), { recursive: true });
519
+ await writeFile2(filePath, lines.join("\n") + "\n", "utf8");
520
+ }
521
+ function freshLines(entries) {
522
+ const out = [];
523
+ for (const [key, value] of Object.entries(entries)) {
524
+ if (value !== void 0) out.push(`${key}=${value}`);
525
+ }
526
+ return out;
527
+ }
528
+ function updateLines(originalContent, entries) {
529
+ let rawLines = originalContent.split(/\r?\n/);
530
+ if (rawLines.length > 0 && rawLines[rawLines.length - 1] === "") {
531
+ rawLines = rawLines.slice(0, -1);
532
+ }
533
+ const keysToWrite = new Set(Object.keys(entries));
534
+ const out = [];
535
+ for (const line of rawLines) {
536
+ const trimmed = line.trim();
537
+ if (trimmed.length === 0 || trimmed.startsWith("#")) {
538
+ out.push(line);
539
+ continue;
540
+ }
541
+ const eq = trimmed.indexOf("=");
542
+ if (eq <= 0) {
543
+ out.push(line);
544
+ continue;
545
+ }
546
+ const key = trimmed.slice(0, eq).trim();
547
+ if (keysToWrite.has(key)) {
548
+ out.push(`${key}=${entries[key]}`);
549
+ keysToWrite.delete(key);
550
+ } else {
551
+ out.push(line);
552
+ }
553
+ }
554
+ for (const key of keysToWrite) {
555
+ const value = entries[key];
556
+ if (value !== void 0) out.push(`${key}=${value}`);
557
+ }
558
+ return out;
559
+ }
505
560
 
506
561
  // src/utils/wiki-path.ts
507
562
  async function resolveInitTimePath(input) {
@@ -630,7 +685,7 @@ function simulateRemoval(adj, removed) {
630
685
 
631
686
  // src/commands/audit.ts
632
687
  import { readFile as readFile5, stat as stat2 } from "fs/promises";
633
- import { dirname as dirname2, resolve, join as join3 } from "path";
688
+ import { dirname as dirname3, resolve, join as join3 } from "path";
634
689
 
635
690
  // src/parsers/citations.ts
636
691
  var FENCE2 = /```[\s\S]*?```/g;
@@ -657,7 +712,7 @@ async function runAudit(input) {
657
712
  if (!fm.ok) return { exitCode: ExitCode.INVALID_FRONTMATTER, result: fm };
658
713
  const split = splitFrontmatter(text);
659
714
  const body = split.ok ? split.data.body : text;
660
- const vault = await findVaultRoot(dirname2(resolve(input.file)));
715
+ const vault = await findVaultRoot(dirname3(resolve(input.file)));
661
716
  if (!vault) return { exitCode: ExitCode.VAULT_PATH_INVALID, result: err("VAULT_PATH_INVALID") };
662
717
  const markers = extractCitationMarkers(body);
663
718
  const resolved = await Promise.all(markers.map(async (m) => {
@@ -688,7 +743,7 @@ async function findVaultRoot(start) {
688
743
  return cur;
689
744
  } catch {
690
745
  }
691
- const parent = dirname2(cur);
746
+ const parent = dirname3(cur);
692
747
  if (parent === cur) return null;
693
748
  cur = parent;
694
749
  }
@@ -700,10 +755,10 @@ import { readdir as readdir2, stat as stat4 } from "fs/promises";
700
755
  import { join as join4 } from "path";
701
756
 
702
757
  // src/utils/install-fs.ts
703
- import { copyFile, mkdir as mkdir2, rename, writeFile as writeFile2, stat as stat3 } from "fs/promises";
704
- import { dirname as dirname3 } from "path";
758
+ import { copyFile, mkdir as mkdir3, rename, writeFile as writeFile3, stat as stat3 } from "fs/promises";
759
+ import { dirname as dirname4 } from "path";
705
760
  async function atomicCopyWithBackup(src, dst) {
706
- await mkdir2(dirname3(dst), { recursive: true });
761
+ await mkdir3(dirname4(dst), { recursive: true });
707
762
  let backupPath = null;
708
763
  try {
709
764
  await stat3(dst);
@@ -721,9 +776,9 @@ async function atomicCopyWithBackup(src, dst) {
721
776
  return ok({ copied: true, backupPath });
722
777
  }
723
778
  async function writeManifest(path, m) {
724
- await mkdir2(dirname3(path), { recursive: true });
779
+ await mkdir3(dirname4(path), { recursive: true });
725
780
  const enriched = { installed_at: (/* @__PURE__ */ new Date()).toISOString(), ...m };
726
- await writeFile2(path, JSON.stringify(enriched, null, 2));
781
+ await writeFile3(path, JSON.stringify(enriched, null, 2));
727
782
  }
728
783
 
729
784
  // src/commands/install.ts
@@ -839,8 +894,8 @@ async function runLang(input) {
839
894
  }
840
895
 
841
896
  // src/commands/init.ts
842
- import { mkdir as mkdir3, readFile as readFile6, stat as stat5, writeFile as writeFile3 } from "fs/promises";
843
- import { join as join7, dirname as dirname4 } from "path";
897
+ import { mkdir as mkdir4, readFile as readFile6, stat as stat5, writeFile as writeFile4 } from "fs/promises";
898
+ import { join as join7, dirname as dirname5 } from "path";
844
899
  var DEFAULT_TAXONOMY = [
845
900
  "research",
846
901
  "comparison",
@@ -899,9 +954,9 @@ async function runInit(input) {
899
954
  }
900
955
  const created = [];
901
956
  try {
902
- await mkdir3(target, { recursive: true });
957
+ await mkdir4(target, { recursive: true });
903
958
  for (const d of VAULT_DIRS) {
904
- await mkdir3(join7(target, d), { recursive: true });
959
+ await mkdir4(join7(target, d), { recursive: true });
905
960
  created.push(d + "/");
906
961
  }
907
962
  } catch (e) {
@@ -913,7 +968,7 @@ async function runInit(input) {
913
968
  try {
914
969
  const schemaTpl = await readFile6(join7(input.templates, "SCHEMA.md"), "utf8");
915
970
  const schema = schemaTpl.replace("{{DOMAIN}}", input.domain).replace("{{WIKI_LANG}}", canonicalLang).replace("{{TAXONOMY_YAML}}", taxonomyYaml);
916
- await writeFile3(join7(target, "SCHEMA.md"), schema, "utf8");
971
+ await writeFile4(join7(target, "SCHEMA.md"), schema, "utf8");
917
972
  created.push("SCHEMA.md");
918
973
  } catch (e) {
919
974
  return { exitCode: ExitCode.WRITE_FAILED, result: err("WRITE_FAILED", { file: "SCHEMA.md", message: String(e) }) };
@@ -921,7 +976,7 @@ async function runInit(input) {
921
976
  try {
922
977
  const idxTpl = await readFile6(join7(input.templates, "index.md"), "utf8");
923
978
  const idx = idxTpl.replace("{{INIT_DATE}}", today);
924
- await writeFile3(join7(target, "index.md"), idx, "utf8");
979
+ await writeFile4(join7(target, "index.md"), idx, "utf8");
925
980
  created.push("index.md");
926
981
  } catch (e) {
927
982
  return { exitCode: ExitCode.WRITE_FAILED, result: err("WRITE_FAILED", { file: "index.md", message: String(e) }) };
@@ -929,17 +984,17 @@ async function runInit(input) {
929
984
  try {
930
985
  const logTpl = await readFile6(join7(input.templates, "log.md"), "utf8");
931
986
  const log = logTpl.replace(/\{\{INIT_DATE\}\}/g, today).replace("{{DOMAIN}}", input.domain).replace("{{WIKI_LANG}}", canonicalLang);
932
- await writeFile3(join7(target, "log.md"), log, "utf8");
987
+ await writeFile4(join7(target, "log.md"), log, "utf8");
933
988
  created.push("log.md");
934
989
  } catch (e) {
935
990
  return { exitCode: ExitCode.WRITE_FAILED, result: err("WRITE_FAILED", { file: "log.md", message: String(e) }) };
936
991
  }
937
992
  try {
938
- await mkdir3(dirname4(envPath), { recursive: true });
993
+ await mkdir4(dirname5(envPath), { recursive: true });
939
994
  const envBody = `WIKI_PATH=${target}
940
995
  WIKI_LANG=${canonicalLang}
941
996
  `;
942
- await writeFile3(envPath, envBody, "utf8");
997
+ await writeFile4(envPath, envBody, "utf8");
943
998
  } catch (e) {
944
999
  return { exitCode: ExitCode.WRITE_FAILED, result: err("WRITE_FAILED", { file: envPath, message: String(e) }) };
945
1000
  }
@@ -1131,7 +1186,7 @@ async function runPagesize(input) {
1131
1186
  }
1132
1187
 
1133
1188
  // src/commands/log-rotate.ts
1134
- import { readFile as readFile10, rename as rename2, writeFile as writeFile4, stat as stat6 } from "fs/promises";
1189
+ import { readFile as readFile10, rename as rename2, writeFile as writeFile5, stat as stat6 } from "fs/promises";
1135
1190
  import { join as join11 } from "path";
1136
1191
  var ENTRY_RE = /^## \[(\d{4})-\d{2}-\d{2}\]/gm;
1137
1192
  async function runLogRotate(input) {
@@ -1172,7 +1227,7 @@ Chronological action log. Newest entries last. Skill writes append entries; lint
1172
1227
 
1173
1228
  - Previous log moved to ${rotatedName}
1174
1229
  `;
1175
- await writeFile4(logPath, fresh, "utf8");
1230
+ await writeFile5(logPath, fresh, "utf8");
1176
1231
  } catch (e) {
1177
1232
  return { exitCode: ExitCode.WRITE_FAILED, result: err("WRITE_FAILED", { message: String(e) }) };
1178
1233
  }
@@ -1236,9 +1291,195 @@ async function runLint(input) {
1236
1291
  };
1237
1292
  }
1238
1293
 
1294
+ // src/commands/config.ts
1295
+ import { readFile as readFile11 } from "fs/promises";
1296
+ import { existsSync } from "fs";
1297
+ import { join as join12 } from "path";
1298
+ function validateKey(key) {
1299
+ return key === "WIKI_PATH" || key === "WIKI_LANG";
1300
+ }
1301
+ function configPath(home) {
1302
+ return join12(home, ".skillwiki", ".env");
1303
+ }
1304
+ async function runConfigGet(input) {
1305
+ if (!validateKey(input.key)) {
1306
+ return { exitCode: ExitCode.INVALID_CONFIG_KEY, result: err("INVALID_CONFIG_KEY", { key: input.key }) };
1307
+ }
1308
+ const map = await parseDotenvFile(configPath(input.home));
1309
+ const value = map[input.key] ?? "";
1310
+ return { exitCode: ExitCode.OK, result: ok({ key: input.key, value, humanHint: value }) };
1311
+ }
1312
+ async function runConfigSet(input) {
1313
+ if (!validateKey(input.key)) {
1314
+ return { exitCode: ExitCode.INVALID_CONFIG_KEY, result: err("INVALID_CONFIG_KEY", { key: input.key }) };
1315
+ }
1316
+ const filePath = configPath(input.home);
1317
+ try {
1318
+ let originalContent;
1319
+ try {
1320
+ originalContent = await readFile11(filePath, "utf8");
1321
+ } catch {
1322
+ }
1323
+ const existing = originalContent !== void 0 ? await parseDotenvFile(filePath) : {};
1324
+ const merged = { ...existing, [input.key]: input.value };
1325
+ await writeDotenv(filePath, merged, originalContent);
1326
+ return { exitCode: ExitCode.OK, result: ok({ key: input.key, value: input.value, written: true, humanHint: `${input.key}=${input.value}` }) };
1327
+ } catch (e) {
1328
+ return { exitCode: ExitCode.CONFIG_WRITE_FAILED, result: err("CONFIG_WRITE_FAILED", { key: input.key, error: String(e) }) };
1329
+ }
1330
+ }
1331
+ async function runConfigList(input) {
1332
+ const map = await parseDotenvFile(configPath(input.home));
1333
+ const entries = Object.entries(map).map(([key, value]) => ({ key, value: value ?? "" }));
1334
+ return { exitCode: ExitCode.OK, result: ok({ entries, humanHint: entries.map((e) => `${e.key}=${e.value}`).join("\n") }) };
1335
+ }
1336
+ async function runConfigPath(input) {
1337
+ const filePath = configPath(input.home);
1338
+ return { exitCode: ExitCode.OK, result: ok({ path: filePath, exists: existsSync(filePath), humanHint: filePath }) };
1339
+ }
1340
+
1341
+ // src/commands/doctor.ts
1342
+ import { existsSync as existsSync2, readdirSync, statSync } from "fs";
1343
+ import { join as join13 } from "path";
1344
+ import { execSync } from "child_process";
1345
+ function pass(id, label, detail) {
1346
+ return { id, label, status: "pass", detail };
1347
+ }
1348
+ function warn(id, label, detail) {
1349
+ return { id, label, status: "warn", detail };
1350
+ }
1351
+ function error(id, label, detail) {
1352
+ return { id, label, status: "error", detail };
1353
+ }
1354
+ function checkNodeVersion() {
1355
+ const major = parseInt(process.version.slice(1).split(".")[0], 10);
1356
+ if (major >= 20) {
1357
+ return pass("node_version", "Node.js version", `v${major} >= 20`);
1358
+ }
1359
+ return error("node_version", "Node.js version", `Node.js v${major} is below minimum v20`);
1360
+ }
1361
+ function checkCliOnPath(argv) {
1362
+ if (argv.length >= 2 && argv[1].endsWith("cli.js")) {
1363
+ return warn("cli_on_path", "skillwiki on PATH", "Running via node cli.js (dev mode) \u2014 PATH check skipped");
1364
+ }
1365
+ if (argv.length >= 2 && argv[1] === "skillwiki") {
1366
+ return pass("cli_on_path", "skillwiki on PATH", "Running as skillwiki \u2014 already on PATH");
1367
+ }
1368
+ try {
1369
+ execSync("which skillwiki 2>/dev/null", { encoding: "utf8" }).trim();
1370
+ return pass("cli_on_path", "skillwiki on PATH", "skillwiki found on PATH");
1371
+ } catch {
1372
+ return warn("cli_on_path", "skillwiki on PATH", "skillwiki not found on PATH");
1373
+ }
1374
+ }
1375
+ async function checkConfigFile(home) {
1376
+ const cfgPath = join13(home, ".skillwiki", ".env");
1377
+ if (!existsSync2(cfgPath)) {
1378
+ return warn("config_file", "Config file exists", `${cfgPath} not found`);
1379
+ }
1380
+ try {
1381
+ const map = await parseDotenvFile(cfgPath);
1382
+ const keys = Object.keys(map);
1383
+ return pass("config_file", "Config file exists", `Found with keys: ${keys.length > 0 ? keys.join(", ") : "(none set)"}`);
1384
+ } catch (e) {
1385
+ return warn("config_file", "Config file exists", `Failed to parse ${cfgPath}: ${String(e)}`);
1386
+ }
1387
+ }
1388
+ async function checkWikiPathSet(input) {
1389
+ const r = await resolveRuntimePath({ flag: void 0, envValue: input.envValue, home: input.home });
1390
+ if (r.ok) {
1391
+ return pass("wiki_path_set", "WIKI_PATH configured", `Resolved via ${r.data.source}: ${r.data.path}`);
1392
+ }
1393
+ return error("wiki_path_set", "WIKI_PATH configured", "No vault configured. Run `skillwiki init` or pass --vault.");
1394
+ }
1395
+ function checkWikiPathExists(resolvedPath) {
1396
+ if (resolvedPath === void 0) {
1397
+ return error("wiki_path_exists", "Vault directory exists", "Cannot check \u2014 WIKI_PATH not resolved");
1398
+ }
1399
+ if (existsSync2(resolvedPath) && statSync(resolvedPath).isDirectory()) {
1400
+ return pass("wiki_path_exists", "Vault directory exists", resolvedPath);
1401
+ }
1402
+ return error("wiki_path_exists", "Vault directory exists", `${resolvedPath} does not exist or is not a directory`);
1403
+ }
1404
+ function checkVaultStructure(resolvedPath) {
1405
+ if (resolvedPath === void 0) {
1406
+ return error("vault_structure", "Vault structure valid", "Cannot check \u2014 WIKI_PATH not resolved");
1407
+ }
1408
+ if (!existsSync2(resolvedPath)) {
1409
+ return error("vault_structure", "Vault structure valid", "Cannot check \u2014 vault directory does not exist");
1410
+ }
1411
+ const missing = [];
1412
+ if (!existsSync2(join13(resolvedPath, "SCHEMA.md"))) missing.push("SCHEMA.md");
1413
+ for (const dir of ["raw", "entities", "concepts", "meta"]) {
1414
+ if (!existsSync2(join13(resolvedPath, dir))) missing.push(dir + "/");
1415
+ }
1416
+ if (missing.length === 0) {
1417
+ return pass("vault_structure", "Vault structure valid", "All required files and directories present");
1418
+ }
1419
+ return error("vault_structure", "Vault structure valid", `Missing: ${missing.join(", ")}`);
1420
+ }
1421
+ function checkSkillsInstalled(home) {
1422
+ const skillsDir = join13(home, ".claude", "skills");
1423
+ if (!existsSync2(skillsDir)) {
1424
+ return warn("skills_installed", "Skills installed", `${skillsDir} not found`);
1425
+ }
1426
+ const found = findSkillMd(skillsDir);
1427
+ if (found.length > 0) {
1428
+ return pass("skills_installed", "Skills installed", `${found.length} SKILL.md file(s) found`);
1429
+ }
1430
+ return warn("skills_installed", "Skills installed", "No SKILL.md files found in ~/.claude/skills/");
1431
+ }
1432
+ function findSkillMd(dir) {
1433
+ const results = [];
1434
+ let entries;
1435
+ try {
1436
+ entries = readdirSync(dir, { withFileTypes: true });
1437
+ } catch {
1438
+ return results;
1439
+ }
1440
+ for (const entry of entries) {
1441
+ if (entry.isFile() && entry.name === "SKILL.md") {
1442
+ results.push(join13(dir, entry.name));
1443
+ } else if (entry.isDirectory()) {
1444
+ results.push(...findSkillMd(join13(dir, entry.name)));
1445
+ }
1446
+ }
1447
+ return results;
1448
+ }
1449
+ async function runDoctor(input) {
1450
+ const checks = [];
1451
+ checks.push(checkNodeVersion());
1452
+ checks.push(checkCliOnPath(input.argv));
1453
+ checks.push(await checkConfigFile(input.home));
1454
+ const wikiPathCheck = await checkWikiPathSet(input);
1455
+ checks.push(wikiPathCheck);
1456
+ const resolved = await resolveRuntimePath({ flag: void 0, envValue: input.envValue, home: input.home });
1457
+ const resolvedPath = resolved.ok ? resolved.data.path : void 0;
1458
+ checks.push(checkWikiPathExists(resolvedPath));
1459
+ checks.push(checkVaultStructure(resolvedPath));
1460
+ checks.push(checkSkillsInstalled(input.home));
1461
+ const summary = {
1462
+ pass: checks.filter((c) => c.status === "pass").length,
1463
+ warn: checks.filter((c) => c.status === "warn").length,
1464
+ error: checks.filter((c) => c.status === "error").length
1465
+ };
1466
+ const exitCode = summary.error > 0 ? ExitCode.DOCTOR_HAS_ERRORS : summary.warn > 0 ? ExitCode.DOCTOR_HAS_WARNINGS : ExitCode.OK;
1467
+ const statusIcon = { pass: "\u2713", warn: "\u26A0", error: "\u2717" };
1468
+ const lines = checks.map((c) => {
1469
+ const icon = statusIcon[c.status];
1470
+ const padded = c.label.padEnd(24);
1471
+ return ` ${icon} ${padded} ${c.detail}`;
1472
+ });
1473
+ lines.push("");
1474
+ lines.push(`${summary.pass} pass \xB7 ${summary.warn} warn \xB7 ${summary.error} error`);
1475
+ const humanHint = lines.join("\n");
1476
+ return { exitCode, result: ok({ checks, summary, humanHint }) };
1477
+ }
1478
+
1239
1479
  // src/cli.ts
1480
+ var pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
1240
1481
  var program = new Command();
1241
- program.name("skillwiki").description("Deterministic helpers for CodeWiki skills").version("0.2.0-beta.3");
1482
+ program.name("skillwiki").description("Deterministic helpers for CodeWiki skills").version(pkg.version);
1242
1483
  program.option("--human", "render terminal-readable output instead of JSON");
1243
1484
  function emit(r) {
1244
1485
  if (program.opts().human) printHuman(r.result);
@@ -1344,6 +1585,17 @@ program.command("lint [vault]").option("--days <n>", "stale threshold", (s) => p
1344
1585
  logThreshold: opts.logThreshold
1345
1586
  }));
1346
1587
  });
1588
+ var configCmd = program.command("config").description("manage skillwiki configuration");
1589
+ configCmd.command("get <key>").description("print the value of a config key").action(async (key) => emit(await runConfigGet({ key, home: process.env.HOME ?? "" })));
1590
+ configCmd.command("set <key> <value>").description("set a config key value").action(async (key, value) => emit(await runConfigSet({ key, value, home: process.env.HOME ?? "" })));
1591
+ configCmd.command("list").description("list all config key=value pairs").action(async () => emit(await runConfigList({ home: process.env.HOME ?? "" })));
1592
+ configCmd.command("path").description("print the config file path").action(async () => emit(await runConfigPath({ home: process.env.HOME ?? "" })));
1593
+ program.command("doctor").description("diagnose skillwiki setup issues").action(async () => emit(await runDoctor({
1594
+ home: process.env.HOME ?? "",
1595
+ envValue: process.env.WIKI_PATH,
1596
+ envLang: process.env.WIKI_LANG,
1597
+ argv: process.argv
1598
+ })));
1347
1599
  program.parseAsync(process.argv).catch((e) => {
1348
1600
  process.stdout.write(JSON.stringify({ ok: false, error: "INTERNAL", detail: { message: String(e) } }) + "\n");
1349
1601
  process.exit(1);
package/package.json CHANGED
@@ -1,9 +1,16 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.2.0-beta.3",
3
+ "version": "0.2.0-beta.4",
4
4
  "type": "module",
5
- "bin": { "skillwiki": "dist/cli.js" },
6
- "files": ["dist", "templates", "skills", "README.md"],
5
+ "bin": {
6
+ "skillwiki": "dist/cli.js"
7
+ },
8
+ "files": [
9
+ "dist",
10
+ "templates",
11
+ "skills",
12
+ "README.md"
13
+ ],
7
14
  "scripts": {
8
15
  "build": "tsup && rm -rf ./skills && cp -r ../skills ./skills",
9
16
  "test": "vitest run",
@@ -23,5 +30,7 @@
23
30
  "typescript": "^5.7.0",
24
31
  "vitest": "^2.1.0"
25
32
  },
26
- "engines": { "node": ">=20" }
33
+ "engines": {
34
+ "node": ">=20"
35
+ }
27
36
  }