skillwiki 0.8.5-beta.1 → 0.8.5-beta.3

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.
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  #!/usr/bin/env node
3
3
  import {
4
+ normalizeDistTag,
4
5
  semverGt
5
- } from "./chunk-XM5IYZX7.js";
6
+ } from "./chunk-E6UWZ3S3.js";
6
7
 
7
8
  // src/auto-update-bg.ts
8
9
  import { execSync } from "child_process";
@@ -10,11 +11,12 @@ import { writeFileSync, mkdirSync } from "fs";
10
11
  import { join, dirname } from "path";
11
12
  var home = process.argv[2];
12
13
  var currentVersion = process.argv[3];
14
+ var distTag = normalizeDistTag(process.argv[4]);
13
15
  if (!home || !currentVersion) process.exit(0);
14
16
  var cacheFile = join(home, ".skillwiki", ".update-cache.json");
15
17
  setTimeout(() => process.exit(0), 3e4);
16
18
  try {
17
- const latest = execSync("npm view skillwiki@latest version", {
19
+ const latest = execSync(`npm view skillwiki@${distTag} version`, {
18
20
  encoding: "utf8",
19
21
  timeout: 15e3
20
22
  }).trim();
@@ -22,10 +24,11 @@ try {
22
24
  const cache = {
23
25
  lastCheck: Date.now(),
24
26
  latestVersion: latest,
25
- currentVersion
27
+ currentVersion,
28
+ distTag
26
29
  };
27
30
  if (semverGt(latest, currentVersion)) {
28
- execSync("npm install -g skillwiki@latest", {
31
+ execSync(`npm install -g skillwiki@${distTag}`, {
29
32
  stdio: "ignore",
30
33
  timeout: 6e4
31
34
  });
@@ -36,7 +39,7 @@ try {
36
39
  } catch {
37
40
  try {
38
41
  mkdirSync(dirname(cacheFile), { recursive: true });
39
- writeFileSync(cacheFile, JSON.stringify({ lastCheck: Date.now(), latestVersion: "", currentVersion }, null, 2));
42
+ writeFileSync(cacheFile, JSON.stringify({ lastCheck: Date.now(), latestVersion: "", currentVersion, distTag }, null, 2));
40
43
  } catch {
41
44
  }
42
45
  }
@@ -40,6 +40,23 @@ function parseSemver(version) {
40
40
  };
41
41
  }
42
42
 
43
+ // src/utils/update-consts.ts
44
+ var DIST_TAG = "latest";
45
+ var CACHE_FILENAME = ".update-cache.json";
46
+ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
47
+ var ENV_DISABLE_KEY = "NO_UPDATE_NOTIFIER";
48
+ var CLI_DISABLE_FLAG = "--no-update-notifier";
49
+ function normalizeDistTag(tag) {
50
+ const value = (tag ?? DIST_TAG).trim();
51
+ return /^[A-Za-z0-9._-]+$/.test(value) ? value : DIST_TAG;
52
+ }
53
+
43
54
  export {
44
- semverGt
55
+ semverGt,
56
+ DIST_TAG,
57
+ CACHE_FILENAME,
58
+ CHECK_INTERVAL_MS,
59
+ ENV_DISABLE_KEY,
60
+ CLI_DISABLE_FLAG,
61
+ normalizeDistTag
45
62
  };
package/dist/cli.js CHANGED
@@ -1,7 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ CACHE_FILENAME,
4
+ CHECK_INTERVAL_MS,
5
+ CLI_DISABLE_FLAG,
6
+ DIST_TAG,
7
+ ENV_DISABLE_KEY,
8
+ normalizeDistTag,
3
9
  semverGt
4
- } from "./chunk-XM5IYZX7.js";
10
+ } from "./chunk-E6UWZ3S3.js";
5
11
  import {
6
12
  git,
7
13
  gitStrict
@@ -4011,7 +4017,7 @@ async function runConfigPath(input) {
4011
4017
  }
4012
4018
 
4013
4019
  // src/commands/doctor.ts
4014
- import { existsSync as existsSync9, lstatSync, readlinkSync, readdirSync, statSync as statSync3, readFileSync as readFileSync7 } from "fs";
4020
+ import { existsSync as existsSync10, lstatSync, readlinkSync, readdirSync as readdirSync2, statSync as statSync3, readFileSync as readFileSync7 } from "fs";
4015
4021
  import { join as join27, resolve as resolve5 } from "path";
4016
4022
  import { execSync as execSync2 } from "child_process";
4017
4023
  import { platform as platform2 } from "os";
@@ -4020,14 +4026,6 @@ import { platform as platform2 } from "os";
4020
4026
  import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
4021
4027
  import { join as join24, dirname as dirname9 } from "path";
4022
4028
  import { spawn } from "child_process";
4023
-
4024
- // src/utils/update-consts.ts
4025
- var CACHE_FILENAME = ".update-cache.json";
4026
- var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1e3;
4027
- var ENV_DISABLE_KEY = "NO_UPDATE_NOTIFIER";
4028
- var CLI_DISABLE_FLAG = "--no-update-notifier";
4029
-
4030
- // src/utils/auto-update.ts
4031
4029
  function cachePath(home) {
4032
4030
  return join24(home, ".skillwiki", CACHE_FILENAME);
4033
4031
  }
@@ -4053,12 +4051,17 @@ function writeCache(home, cache) {
4053
4051
  }
4054
4052
  function latestFromCache(home, currentVersion) {
4055
4053
  const { cache } = readCache(home);
4056
- if (!cache || !cache.latestVersion) return { hasUpdate: false, latest: null };
4054
+ if (!cache || !cache.latestVersion) return { hasUpdate: false, latest: null, distTag: DIST_TAG };
4055
+ const distTag = normalizeDistTag(cache.distTag);
4057
4056
  return {
4058
4057
  hasUpdate: semverGt(cache.latestVersion, currentVersion),
4059
- latest: cache.latestVersion
4058
+ latest: cache.latestVersion,
4059
+ distTag
4060
4060
  };
4061
4061
  }
4062
+ function distTagFromCache(home) {
4063
+ return normalizeDistTag(readCacheRaw(home)?.distTag);
4064
+ }
4062
4065
  function isDisabled() {
4063
4066
  return !!(process.env[ENV_DISABLE_KEY] || process.env.NODE_ENV === "test" || process.argv.includes(CLI_DISABLE_FLAG));
4064
4067
  }
@@ -4066,9 +4069,10 @@ function triggerAutoUpdate(home, currentVersion) {
4066
4069
  if (isDisabled()) return;
4067
4070
  const { isStale: isStale2 } = readCache(home);
4068
4071
  if (!isStale2) return;
4072
+ const distTag = distTagFromCache(home);
4069
4073
  const bgScript = new URL("../auto-update-bg.js", import.meta.url).pathname;
4070
4074
  if (!existsSync7(bgScript)) return;
4071
- const child = spawn(process.execPath, [bgScript, home, currentVersion], {
4075
+ const child = spawn(process.execPath, [bgScript, home, currentVersion, distTag], {
4072
4076
  detached: true,
4073
4077
  stdio: "ignore"
4074
4078
  });
@@ -4078,9 +4082,10 @@ function triggerAutoUpdate(home, currentVersion) {
4078
4082
  }
4079
4083
 
4080
4084
  // src/utils/plugin-registry.ts
4081
- import { readFileSync as readFileSync5 } from "fs";
4085
+ import { existsSync as existsSync8, readdirSync, readFileSync as readFileSync5 } from "fs";
4082
4086
  import { join as join25 } from "path";
4083
4087
  var REGISTRY_PATH = join25(".claude", "plugins", "installed_plugins.json");
4088
+ var CODEX_CONFIG_PATH = join25(".codex", "config.toml");
4084
4089
  var PLUGIN_KEY = "skillwiki@llm-wiki";
4085
4090
  function readInstalledPlugins(home) {
4086
4091
  try {
@@ -4097,6 +4102,102 @@ function findPlugin(home, key = PLUGIN_KEY) {
4097
4102
  if (!entries || entries.length === 0) return null;
4098
4103
  return entries[0];
4099
4104
  }
4105
+ function findPluginInstallations(home, key = PLUGIN_KEY) {
4106
+ const parsed = parsePluginKey(key);
4107
+ if (!parsed) return [];
4108
+ const installs = [];
4109
+ const claudePlugin = findPlugin(home, key);
4110
+ if (claudePlugin) {
4111
+ installs.push({
4112
+ channel: "claude",
4113
+ label: "Claude",
4114
+ key,
4115
+ pluginName: parsed.pluginName,
4116
+ marketplace: parsed.marketplace,
4117
+ installPath: claudePlugin.installPath,
4118
+ version: claudePlugin.version
4119
+ });
4120
+ }
4121
+ const codexPlugin = findCodexPlugin(home, key, parsed.pluginName, parsed.marketplace);
4122
+ if (codexPlugin) installs.push(codexPlugin);
4123
+ return installs;
4124
+ }
4125
+ function findCodexPlugin(home, key, pluginName, marketplace) {
4126
+ const config = readCodexPluginConfig(home, key, marketplace);
4127
+ if (!config?.enabled) return null;
4128
+ const cacheRoot = join25(home, ".codex", "plugins", "cache", marketplace, pluginName);
4129
+ if (!existsSync8(cacheRoot)) return null;
4130
+ let versions;
4131
+ try {
4132
+ versions = readdirSync(cacheRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
4133
+ } catch {
4134
+ return null;
4135
+ }
4136
+ if (versions.length === 0) return null;
4137
+ const version = versions.reduce((latest, candidate) => semverGt(candidate, latest) ? candidate : latest);
4138
+ return {
4139
+ channel: "codex",
4140
+ label: "Codex",
4141
+ key,
4142
+ pluginName,
4143
+ marketplace,
4144
+ installPath: join25(cacheRoot, version),
4145
+ version,
4146
+ sourceType: config.sourceType,
4147
+ source: config.source
4148
+ };
4149
+ }
4150
+ function parsePluginKey(key) {
4151
+ const at = key.lastIndexOf("@");
4152
+ if (at <= 0 || at === key.length - 1) return null;
4153
+ return {
4154
+ pluginName: key.slice(0, at),
4155
+ marketplace: key.slice(at + 1)
4156
+ };
4157
+ }
4158
+ function readCodexPluginConfig(home, key, marketplace) {
4159
+ let raw;
4160
+ try {
4161
+ raw = readFileSync5(join25(home, CODEX_CONFIG_PATH), "utf8");
4162
+ } catch {
4163
+ return null;
4164
+ }
4165
+ const pluginSections = /* @__PURE__ */ new Set([`plugins."${key}"`, `plugins.${key}`]);
4166
+ const marketplaceSections = /* @__PURE__ */ new Set([`marketplaces.${marketplace}`, `marketplaces."${marketplace}"`]);
4167
+ let section = "";
4168
+ let sawPlugin = false;
4169
+ const config = { enabled: false };
4170
+ for (const line of raw.split(/\r?\n/)) {
4171
+ const trimmed = line.trim();
4172
+ if (!trimmed || trimmed.startsWith("#")) continue;
4173
+ const sectionMatch = trimmed.match(/^\[([^\]]+)\]$/);
4174
+ if (sectionMatch) {
4175
+ section = sectionMatch[1];
4176
+ continue;
4177
+ }
4178
+ const kv = trimmed.match(/^([A-Za-z0-9_.-]+)\s*=\s*(.+)$/);
4179
+ if (!kv) continue;
4180
+ const name = kv[1];
4181
+ const value = parseTomlScalar(kv[2]);
4182
+ if (pluginSections.has(section) && name === "enabled") {
4183
+ sawPlugin = true;
4184
+ config.enabled = value === true;
4185
+ } else if (marketplaceSections.has(section) && name === "source_type" && typeof value === "string") {
4186
+ config.sourceType = value;
4187
+ } else if (marketplaceSections.has(section) && name === "source" && typeof value === "string") {
4188
+ config.source = value;
4189
+ }
4190
+ }
4191
+ return sawPlugin ? config : null;
4192
+ }
4193
+ function parseTomlScalar(rawValue) {
4194
+ const value = rawValue.replace(/\s+#.*$/, "").trim();
4195
+ if (value === "true") return true;
4196
+ if (value === "false") return false;
4197
+ const quoted = value.match(/^"((?:\\"|[^"])*)"$/);
4198
+ if (quoted) return quoted[1].replace(/\\"/g, '"');
4199
+ return value;
4200
+ }
4100
4201
 
4101
4202
  // src/utils/s3-mount-health.ts
4102
4203
  import { execSync } from "child_process";
@@ -4361,12 +4462,12 @@ function detectCliChannels(argv, home) {
4361
4462
  const plugin = findPlugin(home);
4362
4463
  if (plugin) {
4363
4464
  const pluginBin = join27(plugin.installPath, "bin", "skillwiki");
4364
- if (existsSync9(pluginBin)) {
4465
+ if (existsSync10(pluginBin)) {
4365
4466
  channels.push({ name: "plugin", path: pluginBin, isDevLink: false });
4366
4467
  }
4367
4468
  }
4368
4469
  const installBin = join27(home, ".claude", "skills", "bin", "skillwiki");
4369
- if (existsSync9(installBin)) {
4470
+ if (existsSync10(installBin)) {
4370
4471
  channels.push({ name: "install", path: installBin, isDevLink: false });
4371
4472
  }
4372
4473
  return channels;
@@ -4418,7 +4519,7 @@ function checkCliChannels(argv, home) {
4418
4519
  }
4419
4520
  async function checkConfigFile(home) {
4420
4521
  const cfgPath = configPath(home);
4421
- if (!existsSync9(cfgPath)) {
4522
+ if (!existsSync10(cfgPath)) {
4422
4523
  return check("warn", "config_file", "Config file exists", `${cfgPath} not found`);
4423
4524
  }
4424
4525
  try {
@@ -4433,7 +4534,7 @@ function checkWikiPathExists(resolvedPath) {
4433
4534
  if (resolvedPath === void 0) {
4434
4535
  return check("error", "wiki_path_exists", "Vault directory exists", "Cannot check \u2014 WIKI_PATH not resolved");
4435
4536
  }
4436
- if (existsSync9(resolvedPath) && statSync3(resolvedPath).isDirectory()) {
4537
+ if (existsSync10(resolvedPath) && statSync3(resolvedPath).isDirectory()) {
4437
4538
  return check("pass", "wiki_path_exists", "Vault directory exists", resolvedPath);
4438
4539
  }
4439
4540
  return check("error", "wiki_path_exists", "Vault directory exists", `${resolvedPath} does not exist or is not a directory`);
@@ -4442,13 +4543,13 @@ function checkVaultStructure(resolvedPath) {
4442
4543
  if (resolvedPath === void 0) {
4443
4544
  return check("error", "vault_structure", "Vault structure valid", "Cannot check \u2014 WIKI_PATH not resolved");
4444
4545
  }
4445
- if (!existsSync9(resolvedPath)) {
4546
+ if (!existsSync10(resolvedPath)) {
4446
4547
  return check("error", "vault_structure", "Vault structure valid", "Cannot check \u2014 vault directory does not exist");
4447
4548
  }
4448
4549
  const missing = [];
4449
- if (!existsSync9(join27(resolvedPath, "SCHEMA.md"))) missing.push("SCHEMA.md");
4550
+ if (!existsSync10(join27(resolvedPath, "SCHEMA.md"))) missing.push("SCHEMA.md");
4450
4551
  for (const dir of ["raw", "entities", "concepts", "meta"]) {
4451
- if (!existsSync9(join27(resolvedPath, dir))) missing.push(dir + "/");
4552
+ if (!existsSync10(join27(resolvedPath, dir))) missing.push(dir + "/");
4452
4553
  }
4453
4554
  if (missing.length === 0) {
4454
4555
  return check("pass", "vault_structure", "Vault structure valid", "All required files and directories present");
@@ -4457,7 +4558,7 @@ function checkVaultStructure(resolvedPath) {
4457
4558
  }
4458
4559
  function checkSkillsInstalled(home, cwd) {
4459
4560
  const srcDir = cwd ? join27(cwd, "packages", "skills") : void 0;
4460
- if (srcDir && existsSync9(srcDir)) {
4561
+ if (srcDir && existsSync10(srcDir)) {
4461
4562
  const found = findInstalledSkillMd(srcDir);
4462
4563
  if (found.length > 0) {
4463
4564
  return check("pass", "skills_installed", "Skills installed", `${found.length} SKILL.md file(s) found (source)`);
@@ -4471,7 +4572,7 @@ function checkSkillsInstalled(home, cwd) {
4471
4572
  }
4472
4573
  }
4473
4574
  const skillsDir = join27(home, ".claude", "skills");
4474
- if (existsSync9(skillsDir)) {
4575
+ if (existsSync10(skillsDir)) {
4475
4576
  const found = findInstalledSkillMd(skillsDir);
4476
4577
  if (found.length > 0) {
4477
4578
  return check("pass", "skills_installed", "Skills installed", `${found.length} SKILL.md file(s) found (CLI install)`);
@@ -4513,32 +4614,54 @@ function checkDuplicateSkills(home) {
4513
4614
  return check(status, "skills_duplicate", "Skills not duplicated", parts.join("; "));
4514
4615
  }
4515
4616
  function checkNpmUpdate(home, currentVersion) {
4516
- const { hasUpdate, latest } = latestFromCache(home, currentVersion);
4617
+ const { hasUpdate, latest, distTag } = latestFromCache(home, currentVersion);
4517
4618
  if (!latest) {
4518
- return check("pass", "npm_update", "npm CLI version", `v${currentVersion} (no cache yet)`);
4619
+ return check("pass", "npm_update", "npm CLI version", `v${currentVersion} (${distTag}: no cache yet)`);
4519
4620
  }
4520
4621
  if (hasUpdate) {
4521
- return check("warn", "npm_update", "npm CLI version", `v${currentVersion} \u2014 update available: v${latest}. Run \`skillwiki update\`.`);
4622
+ return check("warn", "npm_update", "npm CLI version", `v${currentVersion} \u2014 ${distTag} update available: v${latest}. Run \`skillwiki update --tag ${distTag}\`.`);
4522
4623
  }
4523
- return check("pass", "npm_update", "npm CLI version", `v${currentVersion} (latest: v${latest})`);
4624
+ return check("pass", "npm_update", "npm CLI version", `v${currentVersion} (${distTag}: v${latest})`);
4524
4625
  }
4525
4626
  function checkPluginVersionDrift(home, currentVersion) {
4526
- const plugin = findPlugin(home);
4527
- if (!plugin) {
4627
+ const plugins = findPluginInstallations(home);
4628
+ if (plugins.length === 0) {
4528
4629
  return check("pass", "plugin_version_drift", "Plugin/CLI version", "Plugin not installed \u2014 CLI only");
4529
4630
  }
4530
- const pluginVersion = plugin.version;
4531
- if (pluginVersion === currentVersion) {
4532
- return check("pass", "plugin_version_drift", "Plugin/CLI version", `Both at v${currentVersion}`);
4631
+ const drifted = plugins.filter((plugin) => plugin.version !== currentVersion);
4632
+ if (drifted.length === 0) {
4633
+ if (plugins.length === 1 && plugins[0].channel === "claude") {
4634
+ return check("pass", "plugin_version_drift", "Plugin/CLI version", `Both at v${currentVersion}`);
4635
+ }
4636
+ if (plugins.length === 1) {
4637
+ return check("pass", "plugin_version_drift", "Plugin/CLI version", `${plugins[0].label} plugin and CLI both at v${currentVersion}`);
4638
+ }
4639
+ const labels = plugins.map((plugin) => `${plugin.label} plugin`).join(", ");
4640
+ return check("pass", "plugin_version_drift", "Plugin/CLI version", `${labels}, and CLI all at v${currentVersion}`);
4533
4641
  }
4534
- const updateCmd = semverGt(pluginVersion, currentVersion) ? "npm install -g skillwiki@latest" : "claude plugin update skillwiki@llm-wiki";
4642
+ const details = drifted.map((plugin) => {
4643
+ const updateCmd = pluginUpdateCommand(plugin, currentVersion);
4644
+ return `${plugin.label} plugin v${plugin.version} \u2260 CLI v${currentVersion} \u2014 run \`${updateCmd}\``;
4645
+ });
4535
4646
  return check(
4536
4647
  "warn",
4537
4648
  "plugin_version_drift",
4538
4649
  "Plugin/CLI version",
4539
- `Plugin v${pluginVersion} \u2260 CLI v${currentVersion} \u2014 run \`${updateCmd}\``
4650
+ details.join("; ")
4540
4651
  );
4541
4652
  }
4653
+ function pluginUpdateCommand(plugin, currentVersion) {
4654
+ if (semverGt(plugin.version, currentVersion)) {
4655
+ return "npm install -g skillwiki@latest";
4656
+ }
4657
+ if (plugin.channel === "claude") {
4658
+ return "claude plugin update skillwiki@llm-wiki";
4659
+ }
4660
+ if (plugin.sourceType === "git") {
4661
+ return "codex plugin marketplace upgrade llm-wiki && codex plugin remove skillwiki@llm-wiki && codex plugin add skillwiki@llm-wiki";
4662
+ }
4663
+ return "codex plugin remove skillwiki@llm-wiki && codex plugin add skillwiki@llm-wiki";
4664
+ }
4542
4665
  async function checkProfiles(home) {
4543
4666
  const map = await parseDotenvFile(configPath(home));
4544
4667
  const profiles = [];
@@ -4562,7 +4685,7 @@ async function checkProfiles(home) {
4562
4685
  async function checkProjectLocalOverride(cwd) {
4563
4686
  const dir = cwd ?? process.cwd();
4564
4687
  const envPath = join27(dir, ".skillwiki", ".env");
4565
- if (existsSync9(envPath)) {
4688
+ if (existsSync10(envPath)) {
4566
4689
  return check("pass", "project_local", "Project-local config", `Found: ${envPath}`);
4567
4690
  }
4568
4691
  return check("pass", "project_local", "Project-local config", "None");
@@ -4571,7 +4694,7 @@ function checkVaultGitRemote(resolvedPath) {
4571
4694
  if (resolvedPath === void 0) {
4572
4695
  return check("error", "vault_git_remote", "Vault git remote", "Cannot check \u2014 WIKI_PATH not resolved");
4573
4696
  }
4574
- if (!existsSync9(join27(resolvedPath, ".git"))) {
4697
+ if (!existsSync10(join27(resolvedPath, ".git"))) {
4575
4698
  return check("warn", "vault_git_remote", "Vault git remote", "Vault is not a git repository \u2014 sync features unavailable");
4576
4699
  }
4577
4700
  try {
@@ -4594,9 +4717,9 @@ function checkObsidianTemplates(resolvedPath) {
4594
4717
  return check("error", "obsidian_templates", "Obsidian templates", "Cannot check \u2014 WIKI_PATH not resolved");
4595
4718
  }
4596
4719
  const missing = [];
4597
- if (!existsSync9(join27(resolvedPath, "_Templates"))) missing.push("_Templates/");
4598
- if (!existsSync9(join27(resolvedPath, ".obsidian", "templates.json"))) missing.push(".obsidian/templates.json");
4599
- if (!existsSync9(join27(resolvedPath, ".obsidian", "app.json"))) missing.push(".obsidian/app.json");
4720
+ if (!existsSync10(join27(resolvedPath, "_Templates"))) missing.push("_Templates/");
4721
+ if (!existsSync10(join27(resolvedPath, ".obsidian", "templates.json"))) missing.push(".obsidian/templates.json");
4722
+ if (!existsSync10(join27(resolvedPath, ".obsidian", "app.json"))) missing.push(".obsidian/app.json");
4600
4723
  if (missing.length === 0) {
4601
4724
  return check("pass", "obsidian_templates", "Obsidian templates", "Template folder and config present");
4602
4725
  }
@@ -4607,14 +4730,14 @@ function checkDotStoreClean(resolvedPath) {
4607
4730
  return check("error", "dsstore_clean", "No .DS_Store in raw/", "Cannot check \u2014 WIKI_PATH not resolved");
4608
4731
  }
4609
4732
  const rawDir = join27(resolvedPath, "raw");
4610
- if (!existsSync9(rawDir)) {
4733
+ if (!existsSync10(rawDir)) {
4611
4734
  return check("pass", "dsstore_clean", "No .DS_Store in raw/", "raw/ directory not found \u2014 check skipped");
4612
4735
  }
4613
4736
  const found = [];
4614
4737
  (function walk2(dir, rel) {
4615
4738
  let entries;
4616
4739
  try {
4617
- entries = readdirSync(dir, { withFileTypes: true });
4740
+ entries = readdirSync2(dir, { withFileTypes: true });
4618
4741
  } catch {
4619
4742
  return;
4620
4743
  }
@@ -4635,7 +4758,7 @@ function checkSyncLastPush(resolvedPath) {
4635
4758
  if (resolvedPath === void 0) {
4636
4759
  return check("error", "sync_last_push", "Vault sync recency", "Cannot check \u2014 WIKI_PATH not resolved");
4637
4760
  }
4638
- if (!existsSync9(join27(resolvedPath, ".git"))) {
4761
+ if (!existsSync10(join27(resolvedPath, ".git"))) {
4639
4762
  return check("pass", "sync_last_push", "Vault sync recency", "No git repo \u2014 sync check skipped");
4640
4763
  }
4641
4764
  let timestamp;
@@ -4683,7 +4806,7 @@ function checkVaultGitDirty(resolvedPath) {
4683
4806
  if (resolvedPath === void 0) {
4684
4807
  return check("pass", "vault_git_dirty", "Vault git dirty state", "No vault path \u2014 check skipped");
4685
4808
  }
4686
- if (!existsSync9(join27(resolvedPath, ".git"))) {
4809
+ if (!existsSync10(join27(resolvedPath, ".git"))) {
4687
4810
  return check("pass", "vault_git_dirty", "Vault git dirty state", "No git repo \u2014 check skipped");
4688
4811
  }
4689
4812
  try {
@@ -4724,7 +4847,7 @@ function checkVaultGitComparison(resolvedPath, id, label, range, nonZeroSuffix,
4724
4847
  if (resolvedPath === void 0) {
4725
4848
  return check("pass", id, label, "No vault path \u2014 check skipped");
4726
4849
  }
4727
- if (!existsSync9(join27(resolvedPath, ".git"))) {
4850
+ if (!existsSync10(join27(resolvedPath, ".git"))) {
4728
4851
  return check("pass", id, label, "No git repo \u2014 check skipped");
4729
4852
  }
4730
4853
  if (!hasOriginMain(resolvedPath)) {
@@ -4762,7 +4885,7 @@ function isRecentLogLine(line, nowMs) {
4762
4885
  return nowMs - ts <= 24 * 60 * 60 * 1e3;
4763
4886
  }
4764
4887
  function checkVaultGitPullFailures(home) {
4765
- const path = pullLogPaths(home).find((p) => existsSync9(p));
4888
+ const path = pullLogPaths(home).find((p) => existsSync10(p));
4766
4889
  if (!path) {
4767
4890
  return check("pass", "vault_git_pull_failures", "Vault pull failures", "No wiki-pull.log found \u2014 check skipped");
4768
4891
  }
@@ -4791,7 +4914,7 @@ function checkS3MountPerf(resolvedPath) {
4791
4914
  }
4792
4915
  const mountPoint = fuse.mountPoint;
4793
4916
  const conceptsDir = join27(resolvedPath, "concepts");
4794
- if (!existsSync9(conceptsDir)) {
4917
+ if (!existsSync10(conceptsDir)) {
4795
4918
  return check("pass", "s3_mount_perf", "S3 mount performance", `S3 FUSE mount (${mountPoint}), no concepts/ to benchmark`);
4796
4919
  }
4797
4920
  const start = Date.now();
@@ -4974,7 +5097,7 @@ function checkWriteTest(resolvedPath) {
4974
5097
  return check("pass", "s3_write_test", "S3 write test", "local disk \u2014 check skipped");
4975
5098
  }
4976
5099
  const conceptsDir = join27(resolvedPath, "concepts");
4977
- if (!existsSync9(conceptsDir)) {
5100
+ if (!existsSync10(conceptsDir)) {
4978
5101
  return check("pass", "s3_write_test", "S3 write test", "no concepts/ dir to test \u2014 check skipped");
4979
5102
  }
4980
5103
  const result = writeTest(conceptsDir);
@@ -5099,7 +5222,7 @@ function vaultSyncChecks(input) {
5099
5222
  const filterPath = input.filterPath ?? join27(home, ".config", "rclone", "wiki-push-filters.txt");
5100
5223
  const snapshotPath = input.snapshotScriptPath ?? "/root/.hermes/scripts/wiki-snapshot-v3.sh";
5101
5224
  const pushScriptPath = join27(shareDir, "wiki-push.sh");
5102
- const c1 = existsSync9(pushScriptPath) ? check("pass", "vault_sync_installed", "Vault sync installed", `Found: ${pushScriptPath}`) : check("error", "vault_sync_installed", "Vault sync installed", `Script not found at ${pushScriptPath} \u2014 run vault-sync-install`);
5225
+ const c1 = existsSync10(pushScriptPath) ? check("pass", "vault_sync_installed", "Vault sync installed", `Found: ${pushScriptPath}`) : check("error", "vault_sync_installed", "Vault sync installed", `Script not found at ${pushScriptPath} \u2014 run vault-sync-install`);
5103
5226
  let c2;
5104
5227
  try {
5105
5228
  if (isMac) {
@@ -5209,7 +5332,7 @@ function vaultSyncChecks(input) {
5209
5332
  }
5210
5333
  }
5211
5334
  } catch {
5212
- c3 = existsSync9(logDir) ? check(
5335
+ c3 = existsSync10(logDir) ? check(
5213
5336
  "warn",
5214
5337
  "vault_sync_last_push_age",
5215
5338
  "Vault sync last push recency",
@@ -5268,7 +5391,7 @@ function vaultSyncChecks(input) {
5268
5391
  }
5269
5392
  let c4;
5270
5393
  try {
5271
- if (!existsSync9(filterPath)) {
5394
+ if (!existsSync10(filterPath)) {
5272
5395
  c4 = check(
5273
5396
  "error",
5274
5397
  "vault_sync_filter_present",
@@ -5317,7 +5440,7 @@ function vaultSyncChecks(input) {
5317
5440
  );
5318
5441
  } else {
5319
5442
  try {
5320
- if (!existsSync9(snapshotPath)) {
5443
+ if (!existsSync10(snapshotPath)) {
5321
5444
  c5 = check(
5322
5445
  "error",
5323
5446
  "vault_sync_snapshot_guard",
@@ -5357,7 +5480,7 @@ function findSkillMd(dir) {
5357
5480
  const results = [];
5358
5481
  let entries;
5359
5482
  try {
5360
- entries = readdirSync(dir, { withFileTypes: true });
5483
+ entries = readdirSync2(dir, { withFileTypes: true });
5361
5484
  } catch {
5362
5485
  return results;
5363
5486
  }
@@ -5378,12 +5501,12 @@ function findSkillNames(dir) {
5378
5501
  const results = [];
5379
5502
  let entries;
5380
5503
  try {
5381
- entries = readdirSync(dir, { withFileTypes: true });
5504
+ entries = readdirSync2(dir, { withFileTypes: true });
5382
5505
  } catch {
5383
5506
  return results;
5384
5507
  }
5385
5508
  for (const entry of entries) {
5386
- if (entry.isDirectory() && existsSync9(join27(dir, entry.name, "SKILL.md"))) {
5509
+ if (entry.isDirectory() && existsSync10(join27(dir, entry.name, "SKILL.md"))) {
5387
5510
  results.push(entry.name);
5388
5511
  }
5389
5512
  }
@@ -6057,7 +6180,7 @@ async function runUpdate(input) {
6057
6180
  readFileSync8(new URL("../../package.json", import.meta.url), "utf8")
6058
6181
  );
6059
6182
  const currentVersion = pkg2.version;
6060
- const tag = input.distTag ?? "latest";
6183
+ const tag = normalizeDistTag(input.distTag);
6061
6184
  const target = join29(input.home, ".claude", "skills");
6062
6185
  let latest;
6063
6186
  try {
@@ -6074,7 +6197,8 @@ async function runUpdate(input) {
6074
6197
  const cache = {
6075
6198
  lastCheck: Date.now(),
6076
6199
  latestVersion: latest,
6077
- currentVersion
6200
+ currentVersion,
6201
+ distTag: tag
6078
6202
  };
6079
6203
  if (latest === currentVersion) {
6080
6204
  writeCache(input.home, cache);
@@ -6086,7 +6210,7 @@ async function runUpdate(input) {
6086
6210
  wasAlreadyLatest: true,
6087
6211
  version_warnings: [],
6088
6212
  skills_refreshed: false,
6089
- humanHint: `Already on latest ${tag}: v${currentVersion}`
6213
+ humanHint: `Already on npm@${tag}: v${currentVersion}`
6090
6214
  })
6091
6215
  };
6092
6216
  }
@@ -6106,7 +6230,7 @@ async function runUpdate(input) {
6106
6230
  const version_warnings = installResult.warnings;
6107
6231
  const skills_refreshed = installResult.refreshed;
6108
6232
  const hintLines = [
6109
- `Updated skillwiki ${currentVersion} \u2192 ${latest}`,
6233
+ `Updated skillwiki ${currentVersion} \u2192 ${latest} via npm@${tag}`,
6110
6234
  `skills refreshed: ${skills_refreshed}`
6111
6235
  ];
6112
6236
  if (version_warnings.length > 0) {
@@ -6128,7 +6252,7 @@ async function runUpdate(input) {
6128
6252
 
6129
6253
  // src/commands/self-update.ts
6130
6254
  import { execSync as execSync4 } from "child_process";
6131
- import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
6255
+ import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
6132
6256
  import { join as join30 } from "path";
6133
6257
  var DEFAULT_SOURCE_ROOT_SUFFIX = "/Desktop/code/llm-wiki";
6134
6258
  async function runSelfUpdate(input) {
@@ -6136,8 +6260,9 @@ async function runSelfUpdate(input) {
6136
6260
  readFileSync9(new URL("../../package.json", import.meta.url), "utf8")
6137
6261
  ).version;
6138
6262
  const sourceRoot = input.sourceRoot ?? `${input.home}${DEFAULT_SOURCE_ROOT_SUFFIX}`;
6263
+ const distTag = normalizeDistTag(input.distTag);
6139
6264
  const localPkgPath = join30(sourceRoot, "packages", "cli", "package.json");
6140
- const hasLocalSource = existsSync10(localPkgPath);
6265
+ const hasLocalSource = existsSync11(localPkgPath);
6141
6266
  if (input.check) {
6142
6267
  let availableVersion = null;
6143
6268
  let source;
@@ -6151,7 +6276,7 @@ async function runSelfUpdate(input) {
6151
6276
  } else {
6152
6277
  source = "npm";
6153
6278
  try {
6154
- availableVersion = execSync4("npm view skillwiki@latest version", {
6279
+ availableVersion = execSync4(`npm view skillwiki@${distTag} version`, {
6155
6280
  encoding: "utf8",
6156
6281
  timeout: 15e3
6157
6282
  }).trim();
@@ -6221,7 +6346,7 @@ async function runSelfUpdate(input) {
6221
6346
  }
6222
6347
  let latestVersion;
6223
6348
  try {
6224
- latestVersion = execSync4("npm view skillwiki@latest version", {
6349
+ latestVersion = execSync4(`npm view skillwiki@${distTag} version`, {
6225
6350
  encoding: "utf8",
6226
6351
  timeout: 15e3
6227
6352
  }).trim();
@@ -6239,12 +6364,12 @@ async function runSelfUpdate(input) {
6239
6364
  currentVersion,
6240
6365
  availableVersion: latestVersion,
6241
6366
  updateAvailable: false,
6242
- humanHint: `Already on latest: v${currentVersion}`
6367
+ humanHint: `Already on ${distTag}: v${currentVersion}`
6243
6368
  })
6244
6369
  };
6245
6370
  }
6246
6371
  try {
6247
- execSync4("npm install -g skillwiki@latest", {
6372
+ execSync4(`npm install -g skillwiki@${distTag}`, {
6248
6373
  stdio: "pipe",
6249
6374
  timeout: 6e4
6250
6375
  });
@@ -6262,7 +6387,7 @@ async function runSelfUpdate(input) {
6262
6387
  availableVersion: latestVersion,
6263
6388
  updateAvailable: true,
6264
6389
  newVersion: latestVersion,
6265
- humanHint: `Updated skillwiki ${currentVersion} \u2192 ${latestVersion} via npm@latest`
6390
+ humanHint: `Updated skillwiki ${currentVersion} \u2192 ${latestVersion} via npm@${distTag}`
6266
6391
  })
6267
6392
  };
6268
6393
  }
@@ -6445,7 +6570,7 @@ ${entries.map((e) => ` ${e.type}: [[${e.page.replace(/\.md$/, "")}]] \u2014 ${e
6445
6570
  // src/commands/compound.ts
6446
6571
  import { writeFile as writeFile12, mkdir as mkdir11, readdir as readdir7, unlink as unlink4 } from "fs/promises";
6447
6572
  import { join as join33 } from "path";
6448
- import { existsSync as existsSync11 } from "fs";
6573
+ import { existsSync as existsSync12 } from "fs";
6449
6574
  import { readFile as readFile23 } from "fs/promises";
6450
6575
  var RETRO_HEADING_RE = /^## \[(\d{4}-\d{2}-\d{2})(?:\s+[^\]]+)?\] retro \| loop cycle(?: (\d+))?: (.+)$/;
6451
6576
  var FIELD_RE = {
@@ -6563,7 +6688,7 @@ async function runCompound(input) {
6563
6688
  }
6564
6689
  const slug = slugify(entry.cycleName);
6565
6690
  const compoundPath = join33(compoundDir, `${slug}.md`);
6566
- if (existsSync11(compoundPath)) {
6691
+ if (existsSync12(compoundPath)) {
6567
6692
  skipped.push(entry.date);
6568
6693
  continue;
6569
6694
  }
@@ -6601,7 +6726,7 @@ async function runCompound(input) {
6601
6726
  ].join("\n");
6602
6727
  const content = frontmatter + "\n" + body;
6603
6728
  if (!input.dryRun) {
6604
- if (!existsSync11(compoundDir)) {
6729
+ if (!existsSync12(compoundDir)) {
6605
6730
  await mkdir11(compoundDir, { recursive: true });
6606
6731
  }
6607
6732
  await writeFile12(compoundPath, content, "utf8");
@@ -6624,7 +6749,7 @@ async function runCompound(input) {
6624
6749
  }
6625
6750
  async function runCompoundDelete(input) {
6626
6751
  const projectDir = join33(input.vault, "projects", input.project);
6627
- if (!existsSync11(projectDir)) {
6752
+ if (!existsSync12(projectDir)) {
6628
6753
  return {
6629
6754
  exitCode: ExitCode.PROJECT_NOT_FOUND,
6630
6755
  result: err("PROJECT_NOT_FOUND", { slug: input.project, path: projectDir })
@@ -6632,7 +6757,7 @@ async function runCompoundDelete(input) {
6632
6757
  }
6633
6758
  const entryName = input.entry.replace(/\.md$/, "");
6634
6759
  const compoundPath = join33(projectDir, "compound", `${entryName}.md`);
6635
- if (!existsSync11(compoundPath)) {
6760
+ if (!existsSync12(compoundPath)) {
6636
6761
  return {
6637
6762
  exitCode: ExitCode.FILE_NOT_FOUND,
6638
6763
  result: err("FILE_NOT_FOUND", { path: compoundPath })
@@ -6666,7 +6791,7 @@ knowledge.md regenerated`
6666
6791
  }
6667
6792
  async function runCompoundList(input) {
6668
6793
  const compoundDir = join33(input.vault, "projects", input.project, "compound");
6669
- if (!existsSync11(compoundDir)) {
6794
+ if (!existsSync12(compoundDir)) {
6670
6795
  return {
6671
6796
  exitCode: ExitCode.OK,
6672
6797
  result: ok({
@@ -6729,7 +6854,7 @@ no compound entries found`;
6729
6854
 
6730
6855
  // src/commands/observe.ts
6731
6856
  import { mkdir as mkdir12, writeFile as writeFile13 } from "fs/promises";
6732
- import { existsSync as existsSync12, statSync as statSync4 } from "fs";
6857
+ import { existsSync as existsSync13, statSync as statSync4 } from "fs";
6733
6858
  import { join as join34 } from "path";
6734
6859
  import { createHash as createHash4 } from "crypto";
6735
6860
  var ALLOWED_KINDS = /* @__PURE__ */ new Set(["note", "bug", "task", "idea", "session-log"]);
@@ -6753,7 +6878,7 @@ async function runObserve(input) {
6753
6878
  result: err("SCHEME_REJECTED", { message: "Text must not be empty" })
6754
6879
  };
6755
6880
  }
6756
- if (!existsSync12(input.vault) || !statSync4(input.vault).isDirectory()) {
6881
+ if (!existsSync13(input.vault) || !statSync4(input.vault).isDirectory()) {
6757
6882
  return {
6758
6883
  exitCode: ExitCode.VAULT_PATH_INVALID,
6759
6884
  result: err("VAULT_PATH_INVALID", { path: input.vault })
@@ -7257,11 +7382,11 @@ ${body}`;
7257
7382
  }
7258
7383
 
7259
7384
  // src/commands/sync.ts
7260
- import { existsSync as existsSync14 } from "fs";
7385
+ import { existsSync as existsSync15 } from "fs";
7261
7386
  import { join as join37 } from "path";
7262
7387
 
7263
7388
  // src/utils/sync-lock.ts
7264
- import { existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync10, renameSync, unlinkSync as unlinkSync5, writeFileSync as writeFileSync6 } from "fs";
7389
+ import { existsSync as existsSync14, mkdirSync as mkdirSync4, readFileSync as readFileSync10, renameSync, unlinkSync as unlinkSync5, writeFileSync as writeFileSync6 } from "fs";
7265
7390
  import { join as join36 } from "path";
7266
7391
  import { createHash as createHash6 } from "crypto";
7267
7392
  function getSessionId() {
@@ -7274,7 +7399,7 @@ function lockPath(vault) {
7274
7399
  }
7275
7400
  function readLock(vault) {
7276
7401
  const path = lockPath(vault);
7277
- if (!existsSync13(path)) return null;
7402
+ if (!existsSync14(path)) return null;
7278
7403
  try {
7279
7404
  const raw = readFileSync10(path, "utf8");
7280
7405
  return JSON.parse(raw);
@@ -7290,7 +7415,7 @@ function isStale(lock, now) {
7290
7415
  function acquireLock(vault, opts = {}) {
7291
7416
  const path = lockPath(vault);
7292
7417
  const dir = join36(vault, ".skillwiki");
7293
- if (!existsSync13(dir)) {
7418
+ if (!existsSync14(dir)) {
7294
7419
  mkdirSync4(dir, { recursive: true });
7295
7420
  }
7296
7421
  const sessionId = opts.sessionId ?? getSessionId();
@@ -7335,7 +7460,7 @@ function writeLockedFile(path, lock) {
7335
7460
  }
7336
7461
  function releaseLock(vault, opts = {}) {
7337
7462
  const path = lockPath(vault);
7338
- if (!existsSync13(path)) {
7463
+ if (!existsSync14(path)) {
7339
7464
  return { released: false };
7340
7465
  }
7341
7466
  const sessionId = opts.sessionId ?? getSessionId();
@@ -7364,7 +7489,7 @@ function releaseLock(vault, opts = {}) {
7364
7489
  function runSyncStatus(input) {
7365
7490
  const vault = input.vault;
7366
7491
  const includeStashes = input.includeStashes ?? false;
7367
- if (!existsSync14(join37(vault, ".git"))) {
7492
+ if (!existsSync15(join37(vault, ".git"))) {
7368
7493
  return {
7369
7494
  exitCode: ExitCode.VAULT_PATH_INVALID,
7370
7495
  result: ok({
@@ -7442,7 +7567,7 @@ function runSyncStatus(input) {
7442
7567
  }
7443
7568
  async function runSyncPush(input) {
7444
7569
  const vault = input.vault;
7445
- if (!existsSync14(join37(vault, ".git"))) {
7570
+ if (!existsSync15(join37(vault, ".git"))) {
7446
7571
  return {
7447
7572
  exitCode: ExitCode.VAULT_PATH_INVALID,
7448
7573
  result: err("NOT_A_GIT_REPO", { path: vault })
@@ -7565,7 +7690,7 @@ function enableGitLongPathsOnWindows(vault) {
7565
7690
  }
7566
7691
  async function runSyncPull(input) {
7567
7692
  const vault = input.vault;
7568
- if (!existsSync14(join37(vault, ".git"))) {
7693
+ if (!existsSync15(join37(vault, ".git"))) {
7569
7694
  return {
7570
7695
  exitCode: ExitCode.VAULT_PATH_INVALID,
7571
7696
  result: err("NOT_A_GIT_REPO", { path: vault })
@@ -7737,7 +7862,7 @@ function runSyncPeers(input) {
7737
7862
  }
7738
7863
  function runSyncLock(input) {
7739
7864
  const vault = input.vault;
7740
- if (!existsSync14(vault)) {
7865
+ if (!existsSync15(vault)) {
7741
7866
  return {
7742
7867
  exitCode: ExitCode.VAULT_PATH_INVALID,
7743
7868
  result: err("VAULT_PATH_INVALID", { path: vault })
@@ -7772,7 +7897,7 @@ function runSyncLock(input) {
7772
7897
  }
7773
7898
  function runSyncUnlock(input) {
7774
7899
  const vault = input.vault;
7775
- if (!existsSync14(vault)) {
7900
+ if (!existsSync15(vault)) {
7776
7901
  return {
7777
7902
  exitCode: ExitCode.VAULT_PATH_INVALID,
7778
7903
  result: err("VAULT_PATH_INVALID", { path: vault })
@@ -7805,7 +7930,7 @@ function runSyncUnlock(input) {
7805
7930
  }
7806
7931
 
7807
7932
  // src/commands/backup.ts
7808
- import { statSync as statSync5, readdirSync as readdirSync2, readFileSync as readFileSync11, mkdirSync as mkdirSync5, writeFileSync as writeFileSync7 } from "fs";
7933
+ import { statSync as statSync5, readdirSync as readdirSync3, readFileSync as readFileSync11, mkdirSync as mkdirSync5, writeFileSync as writeFileSync7 } from "fs";
7809
7934
  import { join as join38, relative as relative3, dirname as dirname12 } from "path";
7810
7935
  import { PutObjectCommand, HeadObjectCommand, ListObjectsV2Command, GetObjectCommand, DeleteObjectsCommand } from "@aws-sdk/client-s3";
7811
7936
 
@@ -7828,7 +7953,7 @@ function createS3Client(config) {
7828
7953
  // src/commands/backup.ts
7829
7954
  var SKIP_DIRS2 = /* @__PURE__ */ new Set([".git", ".obsidian", "_archive", "node_modules", ".skillwiki"]);
7830
7955
  function* walkMarkdown(dir, base) {
7831
- for (const entry of readdirSync2(dir, { withFileTypes: true })) {
7956
+ for (const entry of readdirSync3(dir, { withFileTypes: true })) {
7832
7957
  if (SKIP_DIRS2.has(entry.name)) continue;
7833
7958
  const full = join38(dir, entry.name);
7834
7959
  if (entry.isDirectory()) {
@@ -7975,11 +8100,11 @@ async function runBackupRestore(input) {
7975
8100
  }
7976
8101
 
7977
8102
  // src/commands/status.ts
7978
- import { existsSync as existsSync15, statSync as statSync6 } from "fs";
8103
+ import { existsSync as existsSync16, statSync as statSync6 } from "fs";
7979
8104
  import { readFile as readFile25 } from "fs/promises";
7980
8105
  import { join as join39 } from "path";
7981
8106
  async function runStatus(input) {
7982
- if (!existsSync15(input.vault)) {
8107
+ if (!existsSync16(input.vault)) {
7983
8108
  return { exitCode: ExitCode.VAULT_PATH_INVALID, result: err("VAULT_PATH_INVALID", { vault: input.vault }) };
7984
8109
  }
7985
8110
  const scan = await scanVault(input.vault);
@@ -8180,7 +8305,7 @@ async function runSeed(input) {
8180
8305
 
8181
8306
  // src/commands/canvas.ts
8182
8307
  import { readFile as readFile26, writeFile as writeFile16 } from "fs/promises";
8183
- import { existsSync as existsSync16 } from "fs";
8308
+ import { existsSync as existsSync17 } from "fs";
8184
8309
  import { join as join41 } from "path";
8185
8310
  var NODE_WIDTH = 240;
8186
8311
  var NODE_HEIGHT = 60;
@@ -8260,7 +8385,7 @@ function buildCanvasEdges(adjacency) {
8260
8385
  }
8261
8386
  async function runCanvasGenerate(input) {
8262
8387
  const graphPath = input.graphPath ?? join41(input.vault, ".skillwiki", "graph.json");
8263
- if (!existsSync16(graphPath)) {
8388
+ if (!existsSync17(graphPath)) {
8264
8389
  return {
8265
8390
  exitCode: ExitCode.FILE_NOT_FOUND,
8266
8391
  result: err("FILE_NOT_FOUND", {
@@ -8463,14 +8588,14 @@ async function loadOrBuildGraph(vault) {
8463
8588
  }
8464
8589
 
8465
8590
  // src/utils/auto-commit.ts
8466
- import { existsSync as existsSync17 } from "fs";
8591
+ import { existsSync as existsSync18 } from "fs";
8467
8592
  import { join as join43 } from "path";
8468
8593
  async function postCommit(vault, exitCode) {
8469
8594
  if (exitCode !== 0) return;
8470
8595
  const home = process.env.HOME ?? "";
8471
8596
  const dotenv = await parseDotenvFile(configPath(home));
8472
8597
  if (dotenv["AUTO_COMMIT"] === "false") return;
8473
- if (!existsSync17(join43(vault, ".git"))) return;
8598
+ if (!existsSync18(join43(vault, ".git"))) return;
8474
8599
  const lastOps = readLastOp(vault);
8475
8600
  if (lastOps.length === 0) return;
8476
8601
  const porcelain = git(vault, ["status", "--porcelain"]);
@@ -8711,13 +8836,14 @@ program.command("frontmatter-fix [vault]").description("fix common frontmatter i
8711
8836
  if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
8712
8837
  else emit(await runFrontmatterFix({ vault: v.vault, dryRun: !!opts.dryRun }), v.vault);
8713
8838
  });
8714
- program.command("update").description("update skillwiki CLI to the latest version").option("--tag <tag>", "npm dist-tag", "latest").action(async (opts) => emit(await runUpdate({
8839
+ program.command("update").description("update skillwiki CLI from npm dist-tag").option("--tag <tag>", "npm dist-tag", "latest").action(async (opts) => emit(await runUpdate({
8715
8840
  home: process.env.HOME ?? "",
8716
8841
  distTag: opts.tag
8717
8842
  })));
8718
- program.command("self-update").description("update skillwiki CLI from local source or npm@latest").option("--check", "check for updates without installing", false).action(async (opts) => emit(await runSelfUpdate({
8843
+ program.command("self-update").description("update skillwiki CLI from local source or npm dist-tag").option("--check", "check for updates without installing", false).option("--tag <tag>", "npm dist-tag", "latest").action(async (opts) => emit(await runSelfUpdate({
8719
8844
  home: process.env.HOME ?? "",
8720
- check: !!opts.check
8845
+ check: !!opts.check,
8846
+ distTag: opts.tag
8721
8847
  })));
8722
8848
  program.command("transcripts [vault]").description("list transcript files in raw/transcripts/").option("--since <date>", "only files ingested on or after this date (YYYY-MM-DD)").option("--wiki <name>", "wiki profile name").action(async (vault, opts) => {
8723
8849
  const v = await resolveVaultArg(vault, opts.wiki);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.8.5-beta.1",
3
+ "version": "0.8.5-beta.3",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "skillwiki": "dist/cli.js"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.8.5-beta.1",
3
+ "version": "0.8.5-beta.3",
4
4
  "skills": "./",
5
5
  "description": "Project-aware Karpathy-style knowledge base for Claude Code: 18 prompt-only skills (wiki-*, proj-*, using-skillwiki) backed by the deterministic `skillwiki` CLI.",
6
6
  "author": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillwiki",
3
- "version": "0.8.5-beta.1",
3
+ "version": "0.8.5-beta.3",
4
4
  "description": "Project-aware Karpathy-style knowledge base for Codex with 18 prompt-only skills backed by the deterministic skillwiki CLI.",
5
5
  "author": {
6
6
  "name": "karlorz",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillwiki/skills",
3
- "version": "0.8.5-beta.1",
3
+ "version": "0.8.5-beta.3",
4
4
  "private": true,
5
5
  "files": [
6
6
  "wiki-*",