skillwiki 0.10.108 → 0.10.110

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 (30) hide show
  1. package/dist/{chunk-JCDAEZVD.js → chunk-5MV5SSRM.js} +1 -1
  2. package/dist/{chunk-Z4NCF6K6.js → chunk-6X6PPQNI.js} +481 -179
  3. package/dist/{chunk-DTTKCCQ4.js → chunk-KX5Y3GSX.js} +2 -2
  4. package/dist/{chunk-QU2IXZRN.js → chunk-NA3TZ4JN.js} +2 -2
  5. package/dist/{chunk-PGD3J2GE.js → chunk-QU2CKXM4.js} +49 -37
  6. package/dist/{chunk-GJC2CI3W.js → chunk-R2DJ7IJ5.js} +103 -0
  7. package/dist/{chunk-HMHMCPCE.js → chunk-WPJHDRTP.js} +1 -1
  8. package/dist/cli.js +135 -101
  9. package/dist/{index-projection-ESBJOBS7.js → index-projection-6XGESSHV.js} +3 -3
  10. package/dist/{managed-write-preflight-AYD3CJYD.js → managed-write-preflight-JPOBVVSU.js} +4 -4
  11. package/dist/skillwiki-mcp.js +7 -7
  12. package/dist/sources-CLOF5VAT.js +9 -0
  13. package/dist/vault-sync/scripts/wiki-snapshot.sh +20 -12
  14. package/package.json +1 -1
  15. package/skills/.claude-plugin/plugin.json +1 -1
  16. package/skills/.codex-plugin/plugin.json +1 -1
  17. package/skills/.cursor-plugin/plugin.json +1 -1
  18. package/skills/package.json +1 -1
  19. package/skills/skills/skillwiki-connect/SKILL.md +8 -0
  20. package/skills/skills/skillwiki-mcp/SKILL.md +8 -0
  21. package/skills/skills/using-skillwiki/SKILL.md +1 -1
  22. package/skills/skills/wiki-init/SKILL.md +12 -11
  23. package/skills/skillwiki-connect/SKILL.md +8 -0
  24. package/skills/skillwiki-mcp/SKILL.md +8 -0
  25. package/skills/using-skillwiki/SKILL.md +1 -1
  26. package/skills/wiki-init/SKILL.md +12 -11
  27. package/templates/launchd/com.karlchow.skillwiki-clip-outbox.plist +22 -0
  28. package/templates/web-clipper/llm-wiki-clippings.json +1 -1
  29. package/templates/web-clipper/readme.txt +13 -13
  30. package/dist/sources-QTQSZMST.js +0 -9
package/dist/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CAPTURE_HYGIENE_CONTRACT,
4
+ CLIP_NOT_CONFIGURED,
4
5
  DEFAULT_CAPTURE_BUDGET,
5
6
  DEFAULT_DIRTY_VOLUME_THRESHOLD,
6
7
  DEFAULT_MCP_URL,
@@ -21,6 +22,8 @@ import {
21
22
  guardProtectedVaultWrite,
22
23
  isEventLedgerPath,
23
24
  isFailedRunStatus,
25
+ loadClipOutboxConfig,
26
+ mcpAuthFromEnv,
24
27
  measureDirtyVolume,
25
28
  memoryAuthorityTiersRank,
26
29
  mergeMcpAuthIntoEnv,
@@ -62,8 +65,9 @@ import {
62
65
  scanConflictMarkerBlocksInText,
63
66
  snapshotterHealthChecks,
64
67
  upsertIndexEntry,
65
- vectorIndexStatus
66
- } from "./chunk-Z4NCF6K6.js";
68
+ vectorIndexStatus,
69
+ withMcpClient
70
+ } from "./chunk-6X6PPQNI.js";
67
71
  import {
68
72
  normalizeDistTag,
69
73
  readCache,
@@ -76,7 +80,7 @@ import {
76
80
  UNMANAGED_START,
77
81
  renderRootIndex,
78
82
  writeRootIndexProjection
79
- } from "./chunk-DTTKCCQ4.js";
83
+ } from "./chunk-KX5Y3GSX.js";
80
84
  import {
81
85
  FLEET_REL_PATH,
82
86
  REDACTED_MALFORMED_REFERENCE,
@@ -133,6 +137,7 @@ import {
133
137
  resolveFleetHostId,
134
138
  resolveInitTimePath,
135
139
  resolveRuntimePath,
140
+ resolveSkillwikiHome,
136
141
  resolveWikiS3Remote,
137
142
  rewriteRawSourceReferences,
138
143
  runAudit,
@@ -168,12 +173,12 @@ import {
168
173
  supersedeStaleReviewRequiredJournals,
169
174
  taxonomyCommentForPage,
170
175
  writeDotenv
171
- } from "./chunk-PGD3J2GE.js";
176
+ } from "./chunk-QU2CKXM4.js";
172
177
  import {
173
178
  assertTargetInsideVault,
174
179
  atomicWriteText,
175
180
  prepareTypedPage
176
- } from "./chunk-HMHMCPCE.js";
181
+ } from "./chunk-WPJHDRTP.js";
177
182
  import {
178
183
  applySourceDisposition,
179
184
  decodeSourceActionApproval,
@@ -181,7 +186,7 @@ import {
181
186
  inventorySources,
182
187
  planSourceDisposition,
183
188
  runSourcesPending
184
- } from "./chunk-QU2IXZRN.js";
189
+ } from "./chunk-NA3TZ4JN.js";
185
190
  import {
186
191
  authorizeRawOperation,
187
192
  buildSourceReferenceIndex,
@@ -198,7 +203,7 @@ import {
198
203
  resolveExistingRegularFileInsideVault,
199
204
  validateLogEvent,
200
205
  writeLogEvent
201
- } from "./chunk-JCDAEZVD.js";
206
+ } from "./chunk-5MV5SSRM.js";
202
207
  import {
203
208
  ExitCode,
204
209
  MetaSchema,
@@ -219,7 +224,7 @@ import {
219
224
  scanVault,
220
225
  splitFrontmatter,
221
226
  vaultIoConcurrency
222
- } from "./chunk-GJC2CI3W.js";
227
+ } from "./chunk-R2DJ7IJ5.js";
223
228
 
224
229
  // src/cli.ts
225
230
  import { join as join45 } from "path";
@@ -1285,7 +1290,7 @@ gitignore: ${gi.written ? "merged" : "unchanged"} (write-gitignore only)`,
1285
1290
  skipEnv ? "env: skipped" : `env: ${envWritten}`,
1286
1291
  input.noGitignore ? "gitignore: skipped" : `gitignore: ${gitignoreWritten ? "written" : "unchanged"}`,
1287
1292
  `web clipper template: ${WEB_CLIPPER_TEMPLATE_REL}`,
1288
- "web clipper import: open Obsidian Web Clipper Settings and import the JSON in each browser profile"
1293
+ "web clipper import: create ~/Obsidian/clip-outbox (not ~/wiki), import the JSON in each browser profile, select that outbox vault, keep Add to Obsidian"
1289
1294
  ].join("\n");
1290
1295
  if (created.length > 0) {
1291
1296
  appendLastOp(target, {
@@ -3584,6 +3589,30 @@ async function runHealth(input) {
3584
3589
  return { exitCode, result: ok(report) };
3585
3590
  }
3586
3591
 
3592
+ // src/commands/clip-outbox.ts
3593
+ async function runClipOutboxStatus(home) {
3594
+ const resolved = await loadClipOutboxConfig(home);
3595
+ if (!resolved.ok) {
3596
+ return {
3597
+ exitCode: ExitCode.INVALID_CONFIG_VALUE,
3598
+ result: err("INVALID_CONFIG_VALUE", { message: resolved.message })
3599
+ };
3600
+ }
3601
+ if (!resolved.enabled) {
3602
+ return {
3603
+ exitCode: ExitCode.OK,
3604
+ result: ok({ enabled: false, humanHint: CLIP_NOT_CONFIGURED })
3605
+ };
3606
+ }
3607
+ return {
3608
+ exitCode: ExitCode.OK,
3609
+ result: ok({
3610
+ enabled: true,
3611
+ humanHint: `clip-outbox enabled root=${resolved.config.root} mode=${resolved.config.mode}`
3612
+ })
3613
+ };
3614
+ }
3615
+
3587
3616
  // src/commands/connect.ts
3588
3617
  import { chmod, mkdir as mkdir5, readFile as readFile6, stat as stat3 } from "fs/promises";
3589
3618
  import { join as join18 } from "path";
@@ -3671,6 +3700,7 @@ ${formatHostRow(normalizedHash, hostId, granted.vaults)}` };
3671
3700
  }
3672
3701
 
3673
3702
  // src/commands/connect.ts
3703
+ import { CallToolResultSchema } from "@modelcontextprotocol/sdk/types.js";
3674
3704
  var CONNECT_DESCRIPTION = "HTTP MCP leaf connect: ingest a chat-attached env file into ~/.skillwiki/.env (mode 0600). Never runs skillwiki init. Cloud Drive / \u4E91\u76D8 is unsupported.";
3675
3705
  var RESERVED_HOST_IDS = ["msi", "doubao-linux-agent", "macos-dev"];
3676
3706
  var DEST_MODE = 384;
@@ -3712,44 +3742,16 @@ function redactConnectPayload(data, secret) {
3712
3742
  };
3713
3743
  }
3714
3744
  async function readWikiStatus(fetchFn, url, token) {
3715
- const headers = {
3716
- Authorization: `Bearer ${token}`,
3717
- "Content-Type": "application/json",
3718
- Accept: "application/json, text/event-stream"
3719
- };
3720
3745
  try {
3721
- const initRes = await fetchFn(url, {
3722
- method: "POST",
3723
- headers,
3724
- body: JSON.stringify({
3725
- jsonrpc: "2.0",
3726
- id: 1,
3727
- method: "initialize",
3728
- params: {
3729
- protocolVersion: "2025-11-25",
3730
- capabilities: {},
3731
- clientInfo: { name: "skillwiki-connect", version: "0" }
3732
- }
3733
- })
3734
- });
3735
- const session = initRes.headers.get("mcp-session-id");
3736
- if (session) headers["mcp-session-id"] = session;
3737
- const statusRes = await fetchFn(url, {
3738
- method: "POST",
3739
- headers,
3740
- body: JSON.stringify({
3741
- jsonrpc: "2.0",
3742
- id: 2,
3743
- method: "tools/call",
3744
- params: { name: "wiki_status", arguments: {} }
3745
- })
3746
- });
3747
- const raw = await statusRes.text();
3748
- const parsed = JSON.parse(raw.startsWith("data:") ? raw.replace(/^data:\s*/m, "") : raw);
3749
- const structured = parsed.result?.structuredContent;
3750
- let body = structured;
3746
+ const result = await withMcpClient(
3747
+ { fetchFn, url, token, clientName: "skillwiki-connect", version: "0" },
3748
+ async (client, signal) => CallToolResultSchema.parse(await client.callTool({ name: "wiki_status", arguments: {} }, void 0, { signal }))
3749
+ );
3750
+ if (result.isError) return { writer_id: null, ok: null, reconcile_ready: null, error: "wiki_status returned a tool error" };
3751
+ let body = result.structuredContent;
3751
3752
  if (!body) {
3752
- const text = parsed.result?.content?.find((c) => typeof c.text === "string")?.text;
3753
+ const content = result.content.find((item) => item.type === "text");
3754
+ const text = content?.type === "text" ? content.text : void 0;
3753
3755
  if (text) {
3754
3756
  try {
3755
3757
  body = JSON.parse(text);
@@ -3758,17 +3760,26 @@ async function readWikiStatus(fetchFn, url, token) {
3758
3760
  }
3759
3761
  }
3760
3762
  }
3761
- if (!body) return { writer_id: null, ok: null, reconcile_ready: null };
3763
+ if (!body || typeof body !== "object" || Array.isArray(body) || typeof body.ok !== "boolean" || typeof body.reconcile_ready !== "boolean" || body.writer_id !== void 0 && typeof body.writer_id !== "string") {
3764
+ return { writer_id: null, ok: null, reconcile_ready: null, error: "wiki_status returned an invalid status object" };
3765
+ }
3766
+ if (!body.ok) return { writer_id: null, ok: false, reconcile_ready: body.reconcile_ready, error: "wiki_status reported failure" };
3762
3767
  return {
3763
- writer_id: typeof body.writer_id === "string" ? body.writer_id : null,
3764
- ok: typeof body.ok === "boolean" ? body.ok : null,
3765
- reconcile_ready: typeof body.reconcile_ready === "boolean" ? body.reconcile_ready : null
3768
+ writer_id: body.writer_id ?? null,
3769
+ ok: body.ok,
3770
+ reconcile_ready: body.reconcile_ready
3771
+ };
3772
+ } catch (error) {
3773
+ return {
3774
+ writer_id: null,
3775
+ ok: null,
3776
+ reconcile_ready: null,
3777
+ error: redactMcpSecret(error instanceof Error ? error.message : String(error), token)
3766
3778
  };
3767
- } catch {
3768
- return { writer_id: null, ok: null, reconcile_ready: null };
3769
3779
  }
3770
3780
  }
3771
3781
  async function runConnect(input) {
3782
+ input = { ...input, home: resolveSkillwikiHome(input.home, input.env) };
3772
3783
  const dest = join18(input.home, ".skillwiki", ".env");
3773
3784
  const fromFile = input.fromFile?.trim();
3774
3785
  const fromStdin = Boolean(input.fromStdin);
@@ -3878,8 +3889,13 @@ async function runConnect(input) {
3878
3889
  if (doctor.result.ok) {
3879
3890
  handshake = doctor.result.data.checks.find((c) => c.id === "mcp_handshake")?.detail ?? null;
3880
3891
  }
3881
- const url = incomingUrl ?? DEFAULT_MCP_URL;
3882
- const status = await readWikiStatus(input.mcpFetch ?? globalThis.fetch, url, incomingToken);
3892
+ const auth = mcpAuthFromEnv(env);
3893
+ const url = auth.url ?? DEFAULT_MCP_URL;
3894
+ const status = await readWikiStatus(input.mcpFetch ?? globalThis.fetch, url, auth.token ?? incomingToken);
3895
+ if (status.error) {
3896
+ doctorExit = ExitCode.DOCTOR_HAS_ERRORS;
3897
+ handshake = `${handshake ?? ""}; wiki_status verification failed \u2014 ${status.error}`;
3898
+ }
3883
3899
  writerId = status.writer_id;
3884
3900
  statusOk = status.ok;
3885
3901
  reconcileReady = status.reconcile_ready;
@@ -4117,7 +4133,7 @@ ${fmRewritten}
4117
4133
  }
4118
4134
  let indexUpdated = false;
4119
4135
  if (!isRaw) {
4120
- const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-ESBJOBS7.js");
4136
+ const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-6XGESSHV.js");
4121
4137
  const before = await readFile8(join20(input.vault, "index.md"), "utf8").catch(() => "");
4122
4138
  const fullTarget = relPath.replace(/\.md$/, "");
4123
4139
  const bare = fullTarget.split("/").pop() ?? fullTarget;
@@ -4240,7 +4256,7 @@ async function runRemove(input) {
4240
4256
  if (relPath.endsWith(".md") && !relPath.startsWith("raw/")) {
4241
4257
  const { readFile: readFile24 } = await import("fs/promises");
4242
4258
  const { join: pathJoin } = await import("path");
4243
- const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-ESBJOBS7.js");
4259
+ const { renderRootIndex: renderRootIndex2, writeRootIndexProjection: writeRootIndexProjection2 } = await import("./index-projection-6XGESSHV.js");
4244
4260
  const before = await readFile24(pathJoin(input.vault, "index.md"), "utf8").catch(() => "");
4245
4261
  const fullTarget = relPath.replace(/\.md$/, "");
4246
4262
  const bare = fullTarget.split("/").pop() ?? fullTarget;
@@ -6119,7 +6135,6 @@ import {
6119
6135
  unlinkSync,
6120
6136
  writeFileSync as writeFileSync5
6121
6137
  } from "fs";
6122
- import { homedir } from "os";
6123
6138
  import { dirname as dirname6, join as join28 } from "path";
6124
6139
  var PUBLICATION_JOURNAL_SCHEMA = "skillwiki-publication-operation-v1";
6125
6140
  var PHASE_ORDER2 = [
@@ -6148,10 +6163,10 @@ function vaultIdentity(vaultPath) {
6148
6163
  }
6149
6164
  return sha256Hex(real).slice(0, 16);
6150
6165
  }
6151
- function publicationJournalRoot(home = process.env.HOME || homedir()) {
6152
- return join28(home, ".skillwiki", "publication-operations");
6166
+ function publicationJournalRoot(home = resolveSkillwikiHome()) {
6167
+ return join28(resolveSkillwikiHome(home), ".skillwiki", "publication-operations");
6153
6168
  }
6154
- function resolveJournalPaths(vaultPath, operationId2, home = process.env.HOME || homedir()) {
6169
+ function resolveJournalPaths(vaultPath, operationId2, home = resolveSkillwikiHome()) {
6155
6170
  const identity = vaultIdentity(vaultPath);
6156
6171
  const rootDir = publicationJournalRoot(home);
6157
6172
  const vaultDir = join28(rootDir, identity);
@@ -6261,7 +6276,7 @@ function buildIdentitySummary(input) {
6261
6276
  prior_target_sha256: input.prior_target_sha256
6262
6277
  };
6263
6278
  }
6264
- function readPublicationJournal(vaultPath, operationId2, home = process.env.HOME || homedir()) {
6279
+ function readPublicationJournal(vaultPath, operationId2, home = resolveSkillwikiHome()) {
6265
6280
  const { journalPath: journalPath2 } = resolveJournalPaths(vaultPath, operationId2, home);
6266
6281
  if (!existsSync10(journalPath2)) return ok(null);
6267
6282
  let text;
@@ -6279,7 +6294,7 @@ function readPublicationJournal(vaultPath, operationId2, home = process.env.HOME
6279
6294
  return validateRecord(parsed);
6280
6295
  }
6281
6296
  function createPublicationJournal(input) {
6282
- const home = input.home ?? process.env.HOME ?? homedir();
6297
+ const home = resolveSkillwikiHome(input.home);
6283
6298
  const paths = resolveJournalPaths(input.vaultPath, input.operationId, home);
6284
6299
  if (existsSync10(paths.journalPath)) {
6285
6300
  return err("WRITE_FAILED", { message: "journal already exists", path: paths.journalPath });
@@ -6306,7 +6321,7 @@ function createPublicationJournal(input) {
6306
6321
  return ok(record);
6307
6322
  }
6308
6323
  function advancePublicationJournal(input) {
6309
- const home = input.home ?? process.env.HOME ?? homedir();
6324
+ const home = resolveSkillwikiHome(input.home);
6310
6325
  const existing = readPublicationJournal(input.vaultPath, input.operationId, home);
6311
6326
  if (!existing.ok) return existing;
6312
6327
  if (!existing.data) {
@@ -6351,7 +6366,7 @@ function advancePublicationJournal(input) {
6351
6366
  }
6352
6367
  return ok(record);
6353
6368
  }
6354
- function deletePublicationJournal(vaultPath, operationId2, home = process.env.HOME || homedir()) {
6369
+ function deletePublicationJournal(vaultPath, operationId2, home = resolveSkillwikiHome()) {
6355
6370
  const { journalPath: journalPath2 } = resolveJournalPaths(vaultPath, operationId2, home);
6356
6371
  if (!existsSync10(journalPath2)) return ok({ deleted: false });
6357
6372
  try {
@@ -6372,7 +6387,7 @@ function completePublicationJournal(input) {
6372
6387
  const deleted = deletePublicationJournal(
6373
6388
  input.vaultPath,
6374
6389
  input.operationId,
6375
- input.home ?? process.env.HOME ?? homedir()
6390
+ resolveSkillwikiHome(input.home)
6376
6391
  );
6377
6392
  if (!deleted.ok) return deleted;
6378
6393
  return ok({ completed: true });
@@ -8898,7 +8913,7 @@ function refusalErr(code, reason, guidance) {
8898
8913
  }
8899
8914
  async function runSnapshotMaintenanceDryRun(input) {
8900
8915
  const env = input.env ?? process.env;
8901
- const home = input.home ?? env.HOME ?? "";
8916
+ const home = resolveSkillwikiHome(input.home, env);
8902
8917
  const audit = input.auditSink ?? defaultAuditSink(home);
8903
8918
  const now = input.now ?? Date.now();
8904
8919
  const liveVaultPath = input.liveVaultPath ? canonicalize(input.liveVaultPath) : await resolveLiveVault({ env, home });
@@ -9039,7 +9054,7 @@ function makeAuditEvent(input, hostId, now, result, errorCode, approvalId, comma
9039
9054
  }
9040
9055
  async function runSnapshotMaintenanceExecute(input) {
9041
9056
  const env = input.env ?? process.env;
9042
- const home = input.home ?? env.HOME ?? "";
9057
+ const home = resolveSkillwikiHome(input.home, env);
9043
9058
  const audit = input.auditSink ?? defaultAuditSink(home);
9044
9059
  const now = input.now ?? Date.now();
9045
9060
  const isTty = input.isTty ?? !!process.stdin.isTTY;
@@ -9174,7 +9189,7 @@ function extraUnmergedPaths(unmerged) {
9174
9189
  }
9175
9190
  async function authorizeRepairContext(input) {
9176
9191
  const env = input.env ?? process.env;
9177
- const home = input.home ?? env.HOME ?? "";
9192
+ const home = resolveSkillwikiHome(input.home, env);
9178
9193
  const audit = input.auditSink ?? defaultAuditSink(home);
9179
9194
  const now = input.now ?? Date.now();
9180
9195
  const liveVaultPath = input.liveVaultPath ? canonicalize(input.liveVaultPath) : await resolveLiveVault({ env, home });
@@ -9238,7 +9253,7 @@ async function authorizeRepairContext(input) {
9238
9253
  }
9239
9254
  async function runProjectionConflictRepairDryRun(input) {
9240
9255
  const env = input.env ?? process.env;
9241
- const home = input.home ?? env.HOME ?? "";
9256
+ const home = resolveSkillwikiHome(input.home, env);
9242
9257
  const audit = input.auditSink ?? defaultAuditSink(home);
9243
9258
  const now = input.now ?? Date.now();
9244
9259
  const ctx = await authorizeRepairContext(input);
@@ -9341,7 +9356,7 @@ async function performProjectionRepair(input, plan, audit, now) {
9341
9356
  }
9342
9357
  async function runProjectionConflictRepairExecute(input) {
9343
9358
  const env = input.env ?? process.env;
9344
- const home = input.home ?? env.HOME ?? "";
9359
+ const home = resolveSkillwikiHome(input.home, env);
9345
9360
  const audit = input.auditSink ?? defaultAuditSink(home);
9346
9361
  const now = input.now ?? Date.now();
9347
9362
  const isTty = input.isTty ?? !!process.stdin.isTTY;
@@ -9772,11 +9787,20 @@ async function measureAuthoritativeLiveDrift(liveVault, projection) {
9772
9787
 
9773
9788
  // src/copy-status/copy-status.ts
9774
9789
  function liveRecord(p) {
9790
+ if (p.writable === false) {
9791
+ return {
9792
+ state: "blocked",
9793
+ reachable: p.reachable,
9794
+ writable: false,
9795
+ blocked_reason: "s3_write_probe_failed",
9796
+ detail: p.detail ?? "S3 write probe failed"
9797
+ };
9798
+ }
9775
9799
  if (p.unknown || p.reachable === void 0) {
9776
9800
  return { state: "unknown", reachable: p.reachable, detail: p.detail ?? "S3/MCP unmeasured" };
9777
9801
  }
9778
9802
  if (p.reachable) {
9779
- return { state: "ok", reachable: true, detail: p.detail ?? "S3 reachable" };
9803
+ return { state: "ok", reachable: true, ...p.writable === true ? { writable: true } : {}, detail: p.detail ?? "S3 reachable" };
9780
9804
  }
9781
9805
  return { state: "unknown", reachable: false, detail: p.detail ?? "S3 unreachable" };
9782
9806
  }
@@ -9948,6 +9972,14 @@ function defaultCopyStatusDeps(input) {
9948
9972
  };
9949
9973
  return {
9950
9974
  probeLive() {
9975
+ if (input.s3Writable === false) {
9976
+ return {
9977
+ reachable: input.s3Ok,
9978
+ writable: false,
9979
+ detail: `MCP S3 write probe failed${input.s3WritableError ? ` (${input.s3WritableError})` : ""}`
9980
+ };
9981
+ }
9982
+ if (input.s3Ok === true && input.s3Writable === true) return { reachable: true, writable: true, detail: "MCP S3 readable and writable" };
9951
9983
  if (input.s3Ok === true) return { reachable: true, detail: "MCP S3 ok" };
9952
9984
  if (input.s3Ok === false) return { reachable: false, detail: "MCP S3 not ok" };
9953
9985
  const remote = resolveWikiS3Remote({ home: input.home });
@@ -10869,7 +10901,7 @@ function rowHealthy(reachable, timer, runUnhealthy, timerBad, platform3) {
10869
10901
  async function runFleetHealth(input) {
10870
10902
  const deps = input.deps ?? defaultDeps3();
10871
10903
  const env = input.env ?? process.env;
10872
- const home = input.home ?? env.HOME ?? "";
10904
+ const home = resolveSkillwikiHome(input.home, env);
10873
10905
  const osHostname = input.osHostname ?? env.HOSTNAME ?? nodeHostname();
10874
10906
  const vault = input.vault ?? env.WIKI_PATH;
10875
10907
  const file = input.file ?? (vault ? join43(vault, FLEET_REL_PATH) : void 0);
@@ -10974,7 +11006,7 @@ function isValidLastOpPath(file) {
10974
11006
  }
10975
11007
  async function postCommit(vault, exitCode) {
10976
11008
  if (exitCode !== 0) return;
10977
- const home = process.env.HOME ?? "";
11009
+ const home = resolveSkillwikiHome();
10978
11010
  const dotenv = await parseDotenvFile(configPath(home));
10979
11011
  const autoCommit = process.env.AUTO_COMMIT ?? dotenv["AUTO_COMMIT"];
10980
11012
  if (autoCommit === "false") return;
@@ -11192,7 +11224,7 @@ async function emitGuardedVaultWrite(vault, command, run, opts) {
11192
11224
  vault,
11193
11225
  command,
11194
11226
  env: process.env,
11195
- home: process.env.HOME ?? "",
11227
+ home: resolveSkillwikiHome(),
11196
11228
  cwd: process.cwd(),
11197
11229
  osHostname: process.env.HOSTNAME,
11198
11230
  user: process.env.USER
@@ -11211,7 +11243,7 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
11211
11243
  vault,
11212
11244
  command,
11213
11245
  env: process.env,
11214
- home: process.env.HOME ?? "",
11246
+ home: resolveSkillwikiHome(),
11215
11247
  cwd: process.cwd(),
11216
11248
  osHostname: process.env.HOSTNAME,
11217
11249
  user: process.env.USER
@@ -11223,14 +11255,14 @@ async function emitManagedVaultWrite(vault, command, mutate, opts) {
11223
11255
  if (dirty) {
11224
11256
  return emit(dirty, void 0, { postCommit: false });
11225
11257
  }
11226
- const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-AYD3CJYD.js");
11258
+ const { runManagedWriteTransaction: runManagedWriteTransaction2 } = await import("./managed-write-preflight-JPOBVVSU.js");
11227
11259
  const run = await runManagedWriteTransaction2({
11228
11260
  vault,
11229
11261
  command,
11230
11262
  allowImmutableRecord: opts?.allowImmutableRecord === true,
11231
11263
  convergenceVault: opts?.convergenceVault,
11232
11264
  env: process.env,
11233
- home: process.env.HOME ?? "",
11265
+ home: resolveSkillwikiHome(),
11234
11266
  cwd: process.cwd(),
11235
11267
  osHostname: process.env.HOSTNAME,
11236
11268
  user: process.env.USER,
@@ -11476,14 +11508,14 @@ sourcesCmd.command("dispose <raw-path> [vault]").description("permanently delete
11476
11508
  program.command("orphans [vault]").description("find pages not referenced by any other page").option("--wiki <name>", "wiki profile name").action(async (vault, opts) => emit(await runOrphans({
11477
11509
  vault,
11478
11510
  envValue: process.env.WIKI_PATH,
11479
- home: process.env.HOME ?? "",
11511
+ home: resolveSkillwikiHome(),
11480
11512
  wiki: opts.wiki,
11481
11513
  cwd: process.cwd()
11482
11514
  })));
11483
11515
  program.command("audit <file>").description("audit citation markers and source provenance for a vault page").action(async (file) => emit(await runAudit({ file })));
11484
- program.command("install").description("install skillwiki SKILL.md files into ~/.claude/skills/").option("--target <dir>", "target install directory", `${process.env.HOME ?? ""}/.claude/skills/`).option("--dry-run", "preview only", false).option("--skills-root <dir>", "source skills directory (defaults to packaged)").option("--symlink", "create symlinks instead of copies (dev mode \u2014 edits to source are immediately visible)", false).option("--force", "install CLI copies even when the skillwiki@llm-wiki plugin channel is active", false).action(async (opts) => {
11516
+ program.command("install").description("install skillwiki SKILL.md files into ~/.claude/skills/").option("--target <dir>", "target install directory", `${resolveSkillwikiHome()}/.claude/skills/`).option("--dry-run", "preview only", false).option("--skills-root <dir>", "source skills directory (defaults to packaged)").option("--symlink", "create symlinks instead of copies (dev mode \u2014 edits to source are immediately visible)", false).option("--force", "install CLI copies even when the skillwiki@llm-wiki plugin channel is active", false).action(async (opts) => {
11485
11517
  const skillsRoot = opts.skillsRoot ?? new URL("../skills/", import.meta.url).pathname;
11486
- emit(await runInstall({ skillsRoot, target: opts.target, dryRun: !!opts.dryRun, symlink: !!opts.symlink, home: process.env.HOME ?? "", force: !!opts.force }));
11518
+ emit(await runInstall({ skillsRoot, target: opts.target, dryRun: !!opts.dryRun, symlink: !!opts.symlink, home: resolveSkillwikiHome(), force: !!opts.force }));
11487
11519
  });
11488
11520
  program.command("path").description("show the resolved vault path").option("--vault <dir>", "explicit vault override (runtime)").option("--target <dir>", "explicit target override (init-time)").option("--wiki <name>", "wiki profile name").option("--init-time", "use init-time chain instead of runtime", false).option("--explain", "include resolution chain in output", false).option("--plain", "print only the vault path (no JSON wrapper)", false).action(async (opts) => {
11489
11521
  const initTime = !!opts.initTime;
@@ -11491,7 +11523,7 @@ program.command("path").description("show the resolved vault path").option("--va
11491
11523
  const r = await runPath({
11492
11524
  flag,
11493
11525
  envValue: process.env.WIKI_PATH,
11494
- home: process.env.HOME ?? "",
11526
+ home: resolveSkillwikiHome(),
11495
11527
  initTime,
11496
11528
  wiki: opts.wiki,
11497
11529
  cwd: process.cwd(),
@@ -11509,7 +11541,7 @@ program.command("lang").description("get or set the vault language").option("--l
11509
11541
  emit(await runLang({
11510
11542
  flag: opts.lang,
11511
11543
  envValue: process.env.WIKI_LANG,
11512
- home: process.env.HOME ?? "",
11544
+ home: resolveSkillwikiHome(),
11513
11545
  explain: !!opts.explain
11514
11546
  }));
11515
11547
  });
@@ -11519,7 +11551,7 @@ program.command("init").description("bootstrap a new vault with SCHEMA.md, index
11519
11551
  emit(await runInit({
11520
11552
  flag: opts.target,
11521
11553
  envValue: process.env.WIKI_PATH,
11522
- home: process.env.HOME ?? "",
11554
+ home: resolveSkillwikiHome(),
11523
11555
  templates,
11524
11556
  domain: opts.domain,
11525
11557
  taxonomy,
@@ -11537,7 +11569,7 @@ async function resolveVaultArg(arg, wiki) {
11537
11569
  flag: void 0,
11538
11570
  envValue: process.env.WIKI_PATH,
11539
11571
  wikiEnv: process.env.WIKI,
11540
- home: process.env.HOME ?? "",
11572
+ home: resolveSkillwikiHome(),
11541
11573
  wiki,
11542
11574
  cwd: process.cwd()
11543
11575
  });
@@ -11841,7 +11873,7 @@ program.command("health [vault]").description("bounded whole-system wiki health
11841
11873
  else emit(await runHealth({
11842
11874
  vault: v.vault,
11843
11875
  vaultSource: vault ? "flag" : "resolved",
11844
- home: process.env.HOME ?? "",
11876
+ home: resolveSkillwikiHome(),
11845
11877
  envValue: process.env.WIKI_PATH,
11846
11878
  argv: process.argv,
11847
11879
  currentVersion: pkg.version,
@@ -11853,12 +11885,12 @@ program.command("health [vault]").description("bounded whole-system wiki health
11853
11885
  }), void 0, { postCommit: false, humanDetailHints: healthLintDetailHints });
11854
11886
  });
11855
11887
  var configCmd = program.command("config").description("manage skillwiki configuration");
11856
- configCmd.command("get <key>").description("print the value of a config key").action(async (key) => emit(await runConfigGet({ key, home: process.env.HOME ?? "" })));
11857
- configCmd.command("set <key> <value>").description("set a config key value").action(async (key, value) => emit(await runConfigSet({ key, value, home: process.env.HOME ?? "" })));
11858
- configCmd.command("list").option("--profiles", "show wiki profiles summary", false).description("list all config key=value pairs").action(async (opts) => emit(await runConfigList({ home: process.env.HOME ?? "", profiles: !!opts.profiles })));
11859
- configCmd.command("path").description("print the config file path").action(async () => emit(await runConfigPath({ home: process.env.HOME ?? "" })));
11888
+ configCmd.command("get <key>").description("print the value of a config key").action(async (key) => emit(await runConfigGet({ key, home: resolveSkillwikiHome() })));
11889
+ configCmd.command("set <key> <value>").description("set a config key value").action(async (key, value) => emit(await runConfigSet({ key, value, home: resolveSkillwikiHome() })));
11890
+ configCmd.command("list").option("--profiles", "show wiki profiles summary", false).description("list all config key=value pairs").action(async (opts) => emit(await runConfigList({ home: resolveSkillwikiHome(), profiles: !!opts.profiles })));
11891
+ configCmd.command("path").description("print the config file path").action(async () => emit(await runConfigPath({ home: resolveSkillwikiHome() })));
11860
11892
  program.command("doctor").description("diagnose skillwiki setup issues").option("--check-snapshotter", "SSH-probe fleet snapshotter (short timeout)", false).option("--check-mcp", "live-handshake HTTP MCP initialize + tools/list (network)", false).action(async (opts) => emit(await runDoctor({
11861
- home: process.env.HOME ?? "",
11893
+ home: resolveSkillwikiHome(),
11862
11894
  envValue: process.env.WIKI_PATH,
11863
11895
  argv: process.argv,
11864
11896
  currentVersion: pkg.version,
@@ -11867,8 +11899,10 @@ program.command("doctor").description("diagnose skillwiki setup issues").option(
11867
11899
  checkMcp: !!opts.checkMcp,
11868
11900
  env: process.env
11869
11901
  })));
11902
+ var clipOutboxCmd = program.command("clip-outbox").description("dedicated file-level web-clip outbox");
11903
+ clipOutboxCmd.command("status").description("show whether the clip-outbox channel is configured").action(async () => emit(await runClipOutboxStatus(resolveSkillwikiHome())));
11870
11904
  program.command("connect").description(CONNECT_DESCRIPTION).option("--from-file <path>", "chat-attached env file (not Drive / \u4E91\u76D8)").option("--from-stdin", "read env file from stdin (no echo)").option("--dry-run", "validate without writing ~/.skillwiki/.env").option("--force", "overwrite a different existing token").action(async (opts) => emit(await runConnect({
11871
- home: process.env.HOME ?? "",
11905
+ home: resolveSkillwikiHome(),
11872
11906
  fromFile: opts.fromFile,
11873
11907
  fromStdin: !!opts.fromStdin,
11874
11908
  dryRun: !!opts.dryRun,
@@ -11882,7 +11916,7 @@ program.command("status [vault]").description("output vault diagnostics").option
11882
11916
  if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
11883
11917
  else emit(await runStatus({
11884
11918
  vault: v.vault,
11885
- home: process.env.HOME ?? "",
11919
+ home: resolveSkillwikiHome(),
11886
11920
  langEnvValue: process.env.WIKI_LANG
11887
11921
  }), v.vault);
11888
11922
  });
@@ -11891,7 +11925,7 @@ program.command("copy-status [vault]").description("plane-tagged vault freshness
11891
11925
  if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
11892
11926
  else emit(await runCopyStatusCommand({
11893
11927
  vault: v.vault,
11894
- home: process.env.HOME ?? ""
11928
+ home: resolveSkillwikiHome()
11895
11929
  }), v.vault, { postCommit: false });
11896
11930
  });
11897
11931
  program.command("archive <page> [vault]").description("archive a typed-knowledge or raw page").option("--wiki <name>", "wiki profile name").option("--cascade", "scan vault for references (wikilinks + sources arrays); preview by default", false).option("--apply", "with --cascade: mutate sources arrays and archive (without --apply, --cascade is preview-only)", false).option("--approve <token>", "approve an exact state-bound raw archive plan").option("--remote <remote>", "rclone remote root to prune the archived source path, for example seaweed-wiki:cloud/wiki").option("--remote-delete", "delete the archived source path from the remote after local archive", false).option("--max-remote-deletes <n>", "maximum remote object deletes allowed", "1").action(async (page, vault, opts) => {
@@ -11998,11 +12032,11 @@ program.command("frontmatter-fix [vault]").description("fix common frontmatter i
11998
12032
  );
11999
12033
  });
12000
12034
  program.command("update").description("update skillwiki CLI from npm dist-tag").option("--tag <tag>", "npm dist-tag", "latest").action(async (opts) => emit(await runUpdate({
12001
- home: process.env.HOME ?? "",
12035
+ home: resolveSkillwikiHome(),
12002
12036
  distTag: opts.tag
12003
12037
  })));
12004
12038
  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({
12005
- home: process.env.HOME ?? "",
12039
+ home: resolveSkillwikiHome(),
12006
12040
  check: !!opts.check,
12007
12041
  distTag: opts.tag
12008
12042
  })));
@@ -12071,7 +12105,7 @@ syncCmd.command("status [vault]").description("check vault git sync status").opt
12071
12105
  const v = await resolveVaultArg(vault, opts.wiki);
12072
12106
  if (!v.ok) emit({ exitCode: v.exitCode, result: v.payload });
12073
12107
  else {
12074
- const home = process.env.HOME ?? "";
12108
+ const home = resolveSkillwikiHome();
12075
12109
  let snapshotterAlias;
12076
12110
  if (opts.checkSnapshotter) {
12077
12111
  const fleetLoad = await loadFleetManifestAndHost({
@@ -12205,7 +12239,7 @@ backupCmd.command("sync [vault]").description("sync vault to S3-compatible remot
12205
12239
  emit({ exitCode: v.exitCode, result: v.payload });
12206
12240
  return;
12207
12241
  }
12208
- const home = process.env.HOME ?? process.env.USERPROFILE ?? "/tmp";
12242
+ const home = resolveSkillwikiHome();
12209
12243
  const dotenv = await parseDotenvFile(configPath(home));
12210
12244
  emit(await runBackupSync({
12211
12245
  vault: v.vault,
@@ -12224,7 +12258,7 @@ backupCmd.command("restore [vault]").description("restore vault from S3-compatib
12224
12258
  emit({ exitCode: v.exitCode, result: v.payload });
12225
12259
  return;
12226
12260
  }
12227
- const home = process.env.HOME ?? process.env.USERPROFILE ?? "/tmp";
12261
+ const home = resolveSkillwikiHome();
12228
12262
  const dotenv = await parseDotenvFile(configPath(home));
12229
12263
  return emitGuardedVaultWrite(
12230
12264
  v.vault,
@@ -12403,7 +12437,7 @@ fleetCmd.command("context [vault]").description("render compact Runtime Host Con
12403
12437
  file: opts.file,
12404
12438
  hostId: opts.hostId,
12405
12439
  env: process.env,
12406
- home: process.env.HOME ?? "",
12440
+ home: resolveSkillwikiHome(),
12407
12441
  cwd: process.cwd(),
12408
12442
  osHostname: process.env.HOSTNAME,
12409
12443
  user: process.env.USER
@@ -12416,7 +12450,7 @@ fleetCmd.command("health [vault]").description("read-only health probe for skill
12416
12450
  hostId: opts.hostId,
12417
12451
  json: !!opts.json,
12418
12452
  env: process.env,
12419
- home: process.env.HOME ?? "",
12453
+ home: resolveSkillwikiHome(),
12420
12454
  cwd: process.cwd(),
12421
12455
  osHostname: process.env.HOSTNAME,
12422
12456
  user: process.env.USER
@@ -12481,10 +12515,10 @@ mcpAuthCmd.command("issue-host").description("append a host-id hash to the metal
12481
12515
  allowedVaults
12482
12516
  }));
12483
12517
  });
12484
- for (const w of getDeprecatedWarnings(process.env.HOME ?? "")) {
12518
+ for (const w of getDeprecatedWarnings(resolveSkillwikiHome())) {
12485
12519
  process.stderr.write(w + "\n");
12486
12520
  }
12487
- triggerAutoUpdate(process.env.HOME ?? "", pkg.version);
12521
+ triggerAutoUpdate(resolveSkillwikiHome(), pkg.version);
12488
12522
  program.parseAsync(process.argv).catch((e) => {
12489
12523
  process.stdout.write(JSON.stringify({ ok: false, error: "INTERNAL", detail: { message: String(e) } }) + "\n");
12490
12524
  process.exit(ExitCode.INTERNAL_ERROR);
@@ -4,9 +4,9 @@ import {
4
4
  UNMANAGED_START,
5
5
  renderRootIndex,
6
6
  writeRootIndexProjection
7
- } from "./chunk-DTTKCCQ4.js";
8
- import "./chunk-HMHMCPCE.js";
9
- import "./chunk-GJC2CI3W.js";
7
+ } from "./chunk-KX5Y3GSX.js";
8
+ import "./chunk-WPJHDRTP.js";
9
+ import "./chunk-R2DJ7IJ5.js";
10
10
  export {
11
11
  UNMANAGED_END,
12
12
  UNMANAGED_START,
@@ -6,10 +6,10 @@ import {
6
6
  runManagedWritePeerGate,
7
7
  runManagedWritePreflight,
8
8
  runManagedWriteTransaction
9
- } from "./chunk-PGD3J2GE.js";
10
- import "./chunk-HMHMCPCE.js";
11
- import "./chunk-JCDAEZVD.js";
12
- import "./chunk-GJC2CI3W.js";
9
+ } from "./chunk-QU2CKXM4.js";
10
+ import "./chunk-WPJHDRTP.js";
11
+ import "./chunk-5MV5SSRM.js";
12
+ import "./chunk-R2DJ7IJ5.js";
13
13
  export {
14
14
  DEFAULT_MANAGED_WRITE_WAIT_MS,
15
15
  MANAGED_WRITE_POLL_INTERVAL_MS,