token-goat 2.9.30 → 2.9.31

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 (172) hide show
  1. package/README.md +24 -7
  2. package/SECURITY.md +10 -2
  3. package/THIRD_PARTY_NOTICES.md +1 -1
  4. package/dist/native/linux-arm64/tg-hook +0 -0
  5. package/dist/native/linux-x64/tg-hook +0 -0
  6. package/dist/native/win32-arm64/tg-hook.exe +0 -0
  7. package/dist/native/win32-x64/tg-hook.exe +0 -0
  8. package/dist/{token-goat-chunk-QSBRTGM2.mjs → token-goat-chunk-25TRAWET.mjs} +17 -7
  9. package/dist/token-goat-chunk-2KXO6V2B.mjs +203 -0
  10. package/dist/{token-goat-chunk-IVKIZWAB.mjs → token-goat-chunk-2M7E4PF7.mjs} +41 -12
  11. package/dist/{token-goat-chunk-SMVRN2HU.mjs → token-goat-chunk-2UPZGKKY.mjs} +2 -2
  12. package/dist/token-goat-chunk-2WLPWKHV.mjs +135 -0
  13. package/dist/token-goat-chunk-2XBMMDBD.mjs +126 -0
  14. package/dist/token-goat-chunk-32ZOY4N5.mjs +23 -0
  15. package/dist/token-goat-chunk-3EZRNKTK.mjs +188 -0
  16. package/dist/token-goat-chunk-4ADZHI7J.mjs +63 -0
  17. package/dist/token-goat-chunk-4GBVPH3D.mjs +242 -0
  18. package/dist/{token-goat-chunk-KWPNJBDH.mjs → token-goat-chunk-4GILLLWY.mjs} +7 -4
  19. package/dist/{token-goat-chunk-67TQJ76B.mjs → token-goat-chunk-4NAPX7BA.mjs} +36 -3
  20. package/dist/{token-goat-chunk-PU7V3FD6.mjs → token-goat-chunk-4SC7UJYV.mjs} +3354 -2553
  21. package/dist/token-goat-chunk-4SMRO4TO.mjs +366 -0
  22. package/dist/{token-goat-chunk-AFLYLHDH.mjs → token-goat-chunk-4ZBFWLXF.mjs} +283 -427
  23. package/dist/{token-goat-chunk-JDWCRD6M.mjs → token-goat-chunk-57BIAXJL.mjs} +73 -40
  24. package/dist/token-goat-chunk-5AC66HNP.mjs +115 -0
  25. package/dist/token-goat-chunk-5IMLKSOP.mjs +145 -0
  26. package/dist/token-goat-chunk-646E6U44.mjs +398 -0
  27. package/dist/token-goat-chunk-65N4RHP4.mjs +33 -0
  28. package/dist/{token-goat-chunk-JN4XMLSD.mjs → token-goat-chunk-6DG6HWP3.mjs} +8 -2
  29. package/dist/token-goat-chunk-6ENQSNRZ.mjs +573 -0
  30. package/dist/token-goat-chunk-6ZY4GNF2.mjs +91 -0
  31. package/dist/{token-goat-chunk-VPBBTSJR.mjs → token-goat-chunk-76FGDLRO.mjs} +262 -255
  32. package/dist/{token-goat-chunk-7IN2MKDS.mjs → token-goat-chunk-7EZTZOMC.mjs} +121 -289
  33. package/dist/{token-goat-chunk-OJBNYTJP.mjs → token-goat-chunk-7MAOA6X4.mjs} +640 -80
  34. package/dist/token-goat-chunk-7R2ZVVAX.mjs +218 -0
  35. package/dist/{token-goat-chunk-PD5VKH46.mjs → token-goat-chunk-AUNGYYQX.mjs} +2 -2
  36. package/dist/{token-goat-chunk-HG45AF2B.mjs → token-goat-chunk-AUQYRMMH.mjs} +794 -37
  37. package/dist/token-goat-chunk-B3PEKBYG.mjs +128 -0
  38. package/dist/{token-goat-chunk-A3CK6N5Z.mjs → token-goat-chunk-BA4HI6BW.mjs} +1309 -110
  39. package/dist/{token-goat-chunk-JB6QN6VF.mjs → token-goat-chunk-BFCWY73P.mjs} +59 -23
  40. package/dist/{token-goat-chunk-B45VMIIH.mjs → token-goat-chunk-BWGFUZZE.mjs} +7 -5
  41. package/dist/{token-goat-chunk-P4QMM4WK.mjs → token-goat-chunk-C75NA7PL.mjs} +50 -23
  42. package/dist/token-goat-chunk-CBIQ7WTD.mjs +87 -0
  43. package/dist/token-goat-chunk-CETM74KC.mjs +307 -0
  44. package/dist/{token-goat-chunk-H2PHHGM5.mjs → token-goat-chunk-CIMQ2BB3.mjs} +57 -12
  45. package/dist/{token-goat-chunk-N2NMER56.mjs → token-goat-chunk-CJLS3CDL.mjs} +46 -4
  46. package/dist/{token-goat-chunk-VES7EL7O.mjs → token-goat-chunk-CO3UYX6G.mjs} +1 -1
  47. package/dist/token-goat-chunk-COPNXRJM.mjs +154 -0
  48. package/dist/token-goat-chunk-CSJ5L3NL.mjs +479 -0
  49. package/dist/{token-goat-chunk-4LCCNRTG.mjs → token-goat-chunk-CVCEVUGK.mjs} +8 -6
  50. package/dist/{token-goat-chunk-B2RZZCSS.mjs → token-goat-chunk-CXHOFN7R.mjs} +37 -20
  51. package/dist/token-goat-chunk-D735C4QM.mjs +603 -0
  52. package/dist/{token-goat-chunk-APGZXSPS.mjs → token-goat-chunk-DGS2LVNA.mjs} +47 -30
  53. package/dist/{token-goat-chunk-54K3EUV3.mjs → token-goat-chunk-DOWRSMWO.mjs} +1 -1
  54. package/dist/token-goat-chunk-E45INMY3.mjs +71 -0
  55. package/dist/token-goat-chunk-EC5F37F4.mjs +244 -0
  56. package/dist/{token-goat-chunk-XTQAOTSO.mjs → token-goat-chunk-EDBDRVH5.mjs} +4 -1
  57. package/dist/{token-goat-chunk-5BCIJXMO.mjs → token-goat-chunk-EELTBKDM.mjs} +14 -10
  58. package/dist/{token-goat-chunk-W3QCJS6G.mjs → token-goat-chunk-F4HYL64R.mjs} +8 -6
  59. package/dist/token-goat-chunk-F6PAUIEK.mjs +624 -0
  60. package/dist/token-goat-chunk-FDSREWLX.mjs +692 -0
  61. package/dist/token-goat-chunk-GGGG7RWB.mjs +236 -0
  62. package/dist/{token-goat-chunk-C63JQV5K.mjs → token-goat-chunk-GL3ETKSC.mjs} +233 -15
  63. package/dist/token-goat-chunk-GVB2MUST.mjs +1298 -0
  64. package/dist/token-goat-chunk-GWFLAUMQ.mjs +307 -0
  65. package/dist/{token-goat-chunk-ZEJVMUQH.mjs → token-goat-chunk-HLPW63A7.mjs} +2 -2
  66. package/dist/{token-goat-chunk-GOLEOXZP.mjs → token-goat-chunk-HU4TORC5.mjs} +44 -26
  67. package/dist/{token-goat-chunk-Z57YODA2.mjs → token-goat-chunk-I7VKZZAW.mjs} +2 -2
  68. package/dist/{token-goat-chunk-NYKZLXMK.mjs → token-goat-chunk-IA6XSPE3.mjs} +6 -6
  69. package/dist/{token-goat-chunk-E3OQX2XT.mjs → token-goat-chunk-IAGXMHIK.mjs} +81 -42
  70. package/dist/{token-goat-chunk-HYBFA5X3.mjs → token-goat-chunk-IK2DRMFX.mjs} +24 -68
  71. package/dist/{token-goat-chunk-COBQGL5S.mjs → token-goat-chunk-INNPTRUX.mjs} +249 -299
  72. package/dist/{token-goat-chunk-7NADEDKJ.mjs → token-goat-chunk-JJ5BX4F4.mjs} +6 -1
  73. package/dist/{token-goat-chunk-PEPTHRFF.mjs → token-goat-chunk-JVFSHVFJ.mjs} +6 -6
  74. package/dist/token-goat-chunk-KGEFFSHD.mjs +50 -0
  75. package/dist/token-goat-chunk-KQBLRPBN.mjs +433 -0
  76. package/dist/{token-goat-chunk-Q5VTGRH7.mjs → token-goat-chunk-LCNQ2CNN.mjs} +55 -319
  77. package/dist/token-goat-chunk-M3LFJDPU.mjs +58 -0
  78. package/dist/token-goat-chunk-M52KPT3C.mjs +87 -0
  79. package/dist/token-goat-chunk-MBEG42H7.mjs +150 -0
  80. package/dist/{token-goat-chunk-EVC4TOLE.mjs → token-goat-chunk-METECDOH.mjs} +3 -12
  81. package/dist/{token-goat-chunk-T4FK7VOV.mjs → token-goat-chunk-MHX7XCC3.mjs} +2 -1
  82. package/dist/token-goat-chunk-N5LSOVSU.mjs +137 -0
  83. package/dist/{token-goat-chunk-LOBGHXPB.mjs → token-goat-chunk-N5MMR2IW.mjs} +1 -1
  84. package/dist/token-goat-chunk-N7B3JQ2C.mjs +160 -0
  85. package/dist/{token-goat-chunk-RHXKCZX3.mjs → token-goat-chunk-NISNMD7T.mjs} +2182 -2959
  86. package/dist/token-goat-chunk-NMD42SFQ.mjs +434 -0
  87. package/dist/token-goat-chunk-NOSS5VWY.mjs +174 -0
  88. package/dist/{token-goat-chunk-KQNZDCBD.mjs → token-goat-chunk-NSNSPPBG.mjs} +25 -3
  89. package/dist/token-goat-chunk-OBOFIHKN.mjs +38 -0
  90. package/dist/token-goat-chunk-OBRFJ5O5.mjs +76 -0
  91. package/dist/{token-goat-chunk-JTQQGXZH.mjs → token-goat-chunk-ODBT2USM.mjs} +124 -57
  92. package/dist/token-goat-chunk-OS5EM5PP.mjs +107 -0
  93. package/dist/token-goat-chunk-OUKDTVNU.mjs +1178 -0
  94. package/dist/token-goat-chunk-OXFMP75N.mjs +566 -0
  95. package/dist/{token-goat-chunk-DZX2YDPT.mjs → token-goat-chunk-OYIYKDDT.mjs} +2 -2
  96. package/dist/{token-goat-chunk-QCLDAQTS.mjs → token-goat-chunk-P6HQSWQ3.mjs} +50 -53
  97. package/dist/token-goat-chunk-P6VGNTQT.mjs +71 -0
  98. package/dist/{token-goat-chunk-7BXSNBY5.mjs → token-goat-chunk-PFWIMH2E.mjs} +23 -15
  99. package/dist/token-goat-chunk-PJZXIS3G.mjs +39 -0
  100. package/dist/token-goat-chunk-PUO5INXP.mjs +606 -0
  101. package/dist/{token-goat-chunk-GFBSN7BD.mjs → token-goat-chunk-PX5PQWTY.mjs} +22 -250
  102. package/dist/token-goat-chunk-Q5QDBC6O.mjs +111 -0
  103. package/dist/token-goat-chunk-QFNQXSDT.mjs +40 -0
  104. package/dist/{token-goat-chunk-FBNQNSJK.mjs → token-goat-chunk-QH7YVYOY.mjs} +2198 -2782
  105. package/dist/{token-goat-chunk-64FBPDTK.mjs → token-goat-chunk-QLMUHEPB.mjs} +12 -9
  106. package/dist/{token-goat-chunk-RZRTDST7.mjs → token-goat-chunk-QQOJIHL3.mjs} +37 -11
  107. package/dist/{token-goat-chunk-XKI4SEMX.mjs → token-goat-chunk-QQTWJY2O.mjs} +19 -0
  108. package/dist/{token-goat-chunk-U4N3BN2W.mjs → token-goat-chunk-QYHO5CPH.mjs} +3 -2
  109. package/dist/token-goat-chunk-RELAVWAD.mjs +27 -0
  110. package/dist/{token-goat-chunk-ETBHVDB6.mjs → token-goat-chunk-RSLPOBKQ.mjs} +22 -11
  111. package/dist/token-goat-chunk-SAMFDIS2.mjs +712 -0
  112. package/dist/token-goat-chunk-SDELXLDM.mjs +48 -0
  113. package/dist/{token-goat-chunk-4JJS54TR.mjs → token-goat-chunk-SOAFZNNZ.mjs} +161 -38
  114. package/dist/{token-goat-chunk-664RTTUV.mjs → token-goat-chunk-SRTHT7KV.mjs} +21 -16
  115. package/dist/{token-goat-chunk-4FVIAHSI.mjs → token-goat-chunk-T5P5ACNQ.mjs} +7 -6
  116. package/dist/token-goat-chunk-T5YGG4V3.mjs +45 -0
  117. package/dist/token-goat-chunk-TAUZ4OFS.mjs +110 -0
  118. package/dist/{token-goat-chunk-COTXZHTS.mjs → token-goat-chunk-TM6MC754.mjs} +4 -3
  119. package/dist/token-goat-chunk-TWUKBOMP.mjs +72 -0
  120. package/dist/{token-goat-chunk-3CHUNJ2O.mjs → token-goat-chunk-U2KSB4SG.mjs} +8 -5
  121. package/dist/{token-goat-chunk-3Z5S4KGM.mjs → token-goat-chunk-U4WHMG6Y.mjs} +29 -49
  122. package/dist/{token-goat-chunk-PY533T7F.mjs → token-goat-chunk-UGJHGR5A.mjs} +21 -15
  123. package/dist/{token-goat-chunk-CYCEYAEO.mjs → token-goat-chunk-UOUDVA5U.mjs} +1 -1
  124. package/dist/{token-goat-chunk-JDHE26RP.mjs → token-goat-chunk-URRJ33GR.mjs} +16 -5
  125. package/dist/{token-goat-chunk-56EIMS3E.mjs → token-goat-chunk-UZOROKIS.mjs} +23 -17
  126. package/dist/{token-goat-chunk-CZ3LUXYZ.mjs → token-goat-chunk-VIHGGGEI.mjs} +427 -308
  127. package/dist/token-goat-chunk-VTJLAA7P.mjs +21 -0
  128. package/dist/token-goat-chunk-VWDXLT4F.mjs +678 -0
  129. package/dist/{token-goat-chunk-YARZFCZS.mjs → token-goat-chunk-VWZA2H4P.mjs} +62 -53
  130. package/dist/{token-goat-chunk-SQSSNQPE.mjs → token-goat-chunk-VXEXMJDL.mjs} +3979 -4745
  131. package/dist/token-goat-chunk-WBA5SKT4.mjs +547 -0
  132. package/dist/{token-goat-chunk-SJHWVNDQ.mjs → token-goat-chunk-WDH44VAU.mjs} +7 -4
  133. package/dist/token-goat-chunk-X2SUP3EI.mjs +107 -0
  134. package/dist/token-goat-chunk-X3BELZSJ.mjs +125 -0
  135. package/dist/{token-goat-chunk-FZ3NEW5O.mjs → token-goat-chunk-XLRBNZCC.mjs} +13 -8
  136. package/dist/{token-goat-chunk-Z44YO3QZ.mjs → token-goat-chunk-XRKUX6CM.mjs} +1 -1
  137. package/dist/token-goat-chunk-XX6O25RN.mjs +82 -0
  138. package/dist/token-goat-chunk-XZSUHBVS.mjs +65 -0
  139. package/dist/{token-goat-chunk-WY3L4DVT.mjs → token-goat-chunk-Y2ZTQOCL.mjs} +13 -8
  140. package/dist/{token-goat-chunk-UQ5UK2T7.mjs → token-goat-chunk-YB4VMGK2.mjs} +1 -1
  141. package/dist/token-goat-chunk-YBIIY3HR.mjs +51 -0
  142. package/dist/{token-goat-chunk-ZQSJMO2R.mjs → token-goat-chunk-YHVDKQBR.mjs} +105 -105
  143. package/dist/{token-goat-chunk-H2K3QP6H.mjs → token-goat-chunk-YJB5XLWI.mjs} +8 -6
  144. package/dist/{token-goat-chunk-ZCDTCVIS.mjs → token-goat-chunk-YKB6AQG3.mjs} +5 -2
  145. package/dist/token-goat-chunk-YMTG2YA5.mjs +35 -0
  146. package/dist/token-goat-chunk-YPBZYQRV.mjs +40 -0
  147. package/dist/{token-goat-chunk-HOJLCGDP.mjs → token-goat-chunk-YY6AVUFL.mjs} +2033 -2251
  148. package/dist/token-goat-chunk-Z7N5OMMP.mjs +98 -0
  149. package/dist/token-goat-chunk-ZNMNUPAZ.mjs +938 -0
  150. package/dist/token-goat-hook-client.cjs +1 -1
  151. package/dist/token-goat-hook-client.mjs +3 -3
  152. package/dist/token-goat-hook.mjs +67 -38
  153. package/dist/token-goat.core.mjs +4 -4
  154. package/docs/C4_RUNTIME_ARCHITECTURE.md +1 -1
  155. package/docs/cli.md +40 -21
  156. package/docs/install.md +19 -9
  157. package/docs/security.md +5 -3
  158. package/package.json +2 -1
  159. package/dist/token-goat-chunk-5KDMCMF2.mjs +0 -362
  160. package/dist/token-goat-chunk-6QMAS7AB.mjs +0 -42
  161. package/dist/token-goat-chunk-7F2UBPD3.mjs +0 -397
  162. package/dist/token-goat-chunk-ARDNEC2U.mjs +0 -248
  163. package/dist/token-goat-chunk-ATCPY7EQ.mjs +0 -134
  164. package/dist/token-goat-chunk-EFHMMIGP.mjs +0 -68
  165. package/dist/token-goat-chunk-IVALLT3S.mjs +0 -48
  166. package/dist/token-goat-chunk-JDU3EXSU.mjs +0 -65
  167. package/dist/token-goat-chunk-MKPF4CL5.mjs +0 -37
  168. package/dist/token-goat-chunk-RC35RBUL.mjs +0 -312
  169. package/dist/token-goat-chunk-USILZ3T3.mjs +0 -53
  170. package/dist/token-goat-chunk-VL3YIFHZ.mjs +0 -2975
  171. package/dist/token-goat-chunk-XU4P6Z24.mjs +0 -133
  172. package/dist/token-goat-chunk-Y776AENC.mjs +0 -1597
@@ -0,0 +1,479 @@
1
+ import { createRequire as __cjsRequire } from 'node:module';
2
+ const require = __cjsRequire(import.meta.url);
3
+ import {
4
+ windowsPowerShellPath
5
+ } from "./token-goat-chunk-65N4RHP4.mjs";
6
+ import {
7
+ powerShellCommandArgs
8
+ } from "./token-goat-chunk-X2SUP3EI.mjs";
9
+ import {
10
+ init_define_import_meta_env
11
+ } from "./token-goat-chunk-A37V4PBF.mjs";
12
+
13
+ // src/claude_hidden_rules.ts
14
+ init_define_import_meta_env();
15
+ import { execFile, spawnSync } from "node:child_process";
16
+ import * as fs from "node:fs";
17
+ import * as path from "node:path";
18
+ var HARMLESS_FLAGS = /* @__PURE__ */ new Set(["--resume", "-r", "--continue", "-c", "--fork-session", "--session-id", "--name", "-n", "--model", "--fallback-model", "--effort", "--thinking", "--max-thinking-tokens", "--dangerously-skip-permissions", "--allow-dangerously-skip-permissions", "--permission-mode", "--enable-auto-mode", "--verbose", "--debug", "-d", "--debug-file", "--print", "-p", "--output-format", "--include-partial-messages", "--ide", "--chrome", "--no-chrome", "--mcp-config", "--strict-mcp-config", "--append-system-prompt", "--append-system-prompt-file", "--system-prompt", "--system-prompt-file", "--max-turns", "--max-budget-usd", "--worktree", "-w", "--tmux", "--version", "-v", "--allowedtools", "--allowed-tools", "--tools", "--disable-slash-commands", "--no-session-persistence"]);
19
+ var CLI_ENTRYPOINTS = /* @__PURE__ */ new Set(["cli", "sdk-cli"]);
20
+ var BUILTIN_AGENTS = /* @__PURE__ */ new Set(["Explore", "Plan", "general-purpose", "statusline-setup", "claude-code-guide", "web-fetch", "fork", "claude", "worker", "workflow-subagent", "comment-thread-analyst"]);
21
+ var RULE_DIRS = ["skills", "commands", "agents"];
22
+ var RULE_PATH = /(?:^|\/)\.claude\/(?:skills|commands|agents)(?:\/|$)/;
23
+ var AGENT_PATH = /(?:^|\/)\.claude\/agents(?:\/|$)/;
24
+ var CLAUDE_INSIDE = /(?:^|\/)\.claude\//;
25
+ var SCAN_BUDGET = 2e4;
26
+ var NESTED_STAMP_DEPTH = 3;
27
+ var NESTED_STAMP_DIRS = 2e3;
28
+ var SCAN_TTL_MS = 6e4;
29
+ var RACY_MS = 2e3;
30
+ var FILE_HEAD_BYTES = 256 * 1024;
31
+ var OPENS_FRONTMATTER = /^\uFEFF?---[ \t]*\r?\n/;
32
+ var processCache;
33
+ var fixedCache;
34
+ var nestedCache;
35
+ function resetHiddenRuleCache() {
36
+ processCache = void 0;
37
+ fixedCache = void 0;
38
+ nestedCache = void 0;
39
+ }
40
+ function hasProc() {
41
+ return process.platform !== "win32" && fs.existsSync("/proc/self/cmdline");
42
+ }
43
+ function procCommandLine(pid) {
44
+ if (!hasProc()) return void 0;
45
+ const raw = fs.readFileSync(`/proc/${pid}/cmdline`, "utf8");
46
+ return raw.includes("\0\0") ? null : raw.split("\0").join(" ").trim();
47
+ }
48
+ function commandLineQuery(pid) {
49
+ if (process.platform === "win32") return [windowsPowerShellPath(), powerShellCommandArgs(`(Get-CimInstance Win32_Process -Filter 'ProcessId=${pid}').CommandLine`)];
50
+ return ["ps", ["-ww", "-o", "args=", "-p", pid]];
51
+ }
52
+ function executableQuery(pid) {
53
+ return ["ps", ["-ww", "-o", "comm=", "-p", pid]];
54
+ }
55
+ function resolveCommand(word) {
56
+ const candidates = word.includes("/") ? [path.resolve(word)] : (process.env["PATH"] ?? "").split(path.delimiter).filter((d) => d !== "").map((d) => path.join(d, word));
57
+ for (const candidate of candidates) {
58
+ try {
59
+ return fs.realpathSync(candidate);
60
+ } catch {
61
+ continue;
62
+ }
63
+ }
64
+ return null;
65
+ }
66
+ function untitledLine(printed, executable) {
67
+ const line = printed.replace(/\r?\n$/, "");
68
+ if (/\s$/.test(line) || executable === null) return null;
69
+ const first = line.trim().split(/\s+/)[0] ?? "";
70
+ const real = first === "" ? null : resolveCommand(first);
71
+ const exec = executable.trim();
72
+ let execReal;
73
+ try {
74
+ execReal = exec === "" ? null : fs.realpathSync(exec);
75
+ } catch {
76
+ execReal = null;
77
+ }
78
+ return real !== null && real === execReal ? line.trim() : null;
79
+ }
80
+ function commandLine(pid) {
81
+ try {
82
+ const proc = procCommandLine(pid);
83
+ if (proc !== void 0) return proc;
84
+ const [file, args] = commandLineQuery(pid);
85
+ const res = spawnSync(file, args, { encoding: "utf8", windowsHide: true, timeout: 15e3 });
86
+ if (res.error !== void 0 || res.status !== 0) return null;
87
+ if (process.platform === "win32") return res.stdout.trim();
88
+ const [exeFile, exeArgs] = executableQuery(pid);
89
+ const exe = spawnSync(exeFile, exeArgs, { encoding: "utf8", windowsHide: true, timeout: 15e3 });
90
+ return untitledLine(res.stdout, exe.error === void 0 && exe.status === 0 ? exe.stdout : null);
91
+ } catch {
92
+ return null;
93
+ }
94
+ }
95
+ function queryAsync(file, args) {
96
+ return new Promise((resolve2) => {
97
+ execFile(file, args, { encoding: "utf8", windowsHide: true, timeout: 15e3 }, (err, stdout) => resolve2(err === null ? stdout : null));
98
+ });
99
+ }
100
+ async function commandLineAsync(pid) {
101
+ try {
102
+ const proc = procCommandLine(pid);
103
+ if (proc !== void 0) return proc;
104
+ const [file, args] = commandLineQuery(pid);
105
+ const printed = await queryAsync(file, args);
106
+ if (printed === null) return null;
107
+ if (process.platform === "win32") return printed.trim();
108
+ const [exeFile, exeArgs] = executableQuery(pid);
109
+ return untitledLine(printed, await queryAsync(exeFile, exeArgs));
110
+ } catch {
111
+ return null;
112
+ }
113
+ }
114
+ function processKeyOf(env) {
115
+ return `${env["CLAUDE_CODE_SESSION_ID"] ?? ""}:${env["CLAUDE_PID"] ?? ""}:${env["CLAUDE_CODE_ENTRYPOINT"] ?? ""}`;
116
+ }
117
+ function entryReason(env) {
118
+ const entrypoint = env["CLAUDE_CODE_ENTRYPOINT"] ?? "";
119
+ if (!CLI_ENTRYPOINTS.has(entrypoint)) return `entry point ${entrypoint === "" ? "unknown" : entrypoint}`;
120
+ if (!/^[1-9]\d{0,9}$/.test(env["CLAUDE_PID"] ?? "")) return "claude process unknown";
121
+ return null;
122
+ }
123
+ function flagsOf(line) {
124
+ const flags = [];
125
+ const words = (line.match(/"[^"]*"?|\S+/g) ?? []).map((raw) => raw.replace(/^"/, "").replace(/"$/, ""));
126
+ for (let i = 0; i < words.length; i++) {
127
+ const token = words[i];
128
+ if (token === "--") break;
129
+ if (!token.startsWith("-")) continue;
130
+ const eq = token.indexOf("=");
131
+ const next = words[i + 1];
132
+ flags.push({ name: (eq < 0 ? token : token.slice(0, eq)).toLowerCase(), value: eq >= 0 ? token.slice(eq + 1) : next !== void 0 && !next.startsWith("-") ? next : void 0 });
133
+ }
134
+ return flags;
135
+ }
136
+ var PROOF_SOURCES = ["user", "project", "local"];
137
+ function flagsReason(flags) {
138
+ for (const { name, value } of flags) {
139
+ if (name === "--setting-sources") {
140
+ const given = new Set((value ?? "").toLowerCase().split(",").map((v) => v.trim()));
141
+ const dropped = PROOF_SOURCES.find((source) => !given.has(source));
142
+ if (dropped !== void 0) return `claude started with --setting-sources without ${dropped}`;
143
+ } else if (!HARMLESS_FLAGS.has(name)) return `claude started with ${name}`;
144
+ }
145
+ return null;
146
+ }
147
+ function commandLineReason(line) {
148
+ return line === null || line === "" ? "claude command line unreadable" : flagsReason(flagsOf(line));
149
+ }
150
+ function processReason(env) {
151
+ const key = processKeyOf(env);
152
+ if (processCache?.key === key) return processCache.reason;
153
+ const entry = entryReason(env);
154
+ const line = entry === null ? commandLine(env["CLAUDE_PID"]) : null;
155
+ const reason = entry ?? commandLineReason(line);
156
+ if (entry !== null || line !== null) processCache = { key, reason };
157
+ return reason;
158
+ }
159
+ function isOtherHost(env) {
160
+ const entrypoint = env["CLAUDE_CODE_ENTRYPOINT"] ?? "";
161
+ return entrypoint !== "" && !CLI_ENTRYPOINTS.has(entrypoint);
162
+ }
163
+ function commandLineRuleSource(env) {
164
+ return isOtherHost(env) ? null : processReason(env);
165
+ }
166
+ async function primeProcessReason(env) {
167
+ const key = processKeyOf(env);
168
+ if (processCache?.key === key) return;
169
+ const entry = entryReason(env);
170
+ const line = entry === null ? await commandLineAsync(env["CLAUDE_PID"]) : null;
171
+ if (entry !== null || line !== null) processCache = { key, reason: entry ?? commandLineReason(line) };
172
+ }
173
+ function frontmatter(text) {
174
+ return /^\uFEFF?---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*(?:\r?\n|$)/.exec(text)?.[1];
175
+ }
176
+ function frontmatterAddsRule(front) {
177
+ if (front.includes("PermissionRequest")) return true;
178
+ const lines = front.split(/\r?\n/);
179
+ for (let i = 0; i < lines.length; i++) {
180
+ const m = /^\s*["']?disallowed[-_]?tools["']?\s*:(.*)$/i.exec(lines[i]);
181
+ if (m === null) continue;
182
+ let value = m[1];
183
+ for (let j = i + 1; j < lines.length && /^[\s-]/.test(lines[j]); j++) value += ` ${lines[j]}`;
184
+ if (value.split(/[\s,[\]"'-]+/).some((t) => t !== "" && !/^[A-Za-z0-9_*.]+$/.test(t))) return true;
185
+ }
186
+ return false;
187
+ }
188
+ function newScan(helpers, stamped) {
189
+ return { helpers, budget: SCAN_BUDGET, reason: null, stamps: stamped ? /* @__PURE__ */ new Map() : void 0, agents: /* @__PURE__ */ new Set(), pluginAgents: /* @__PURE__ */ new Set(), startedAt: Date.now(), volatile: false, walked: /* @__PURE__ */ new Set() };
190
+ }
191
+ function result(scan) {
192
+ return { reason: scan.reason, stamps: scan.stamps ?? /* @__PURE__ */ new Map(), agents: scan.agents, pluginAgents: scan.pluginAgents, volatile: scan.volatile };
193
+ }
194
+ function stamp(file) {
195
+ try {
196
+ const st = fs.statSync(file);
197
+ return `${st.mtimeMs}:${st.isDirectory() ? "dir" : st.size}`;
198
+ } catch (err) {
199
+ const code = err.code;
200
+ return code === "ENOENT" || code === "ENOTDIR" ? "absent" : "unreadable";
201
+ }
202
+ }
203
+ function record(scan, file) {
204
+ if (scan.stamps === void 0) return;
205
+ const was = stamp(file);
206
+ scan.stamps.set(file, was);
207
+ if (was === "unreadable" || Number(was.slice(0, was.indexOf(":"))) > scan.startedAt - RACY_MS) scan.volatile = true;
208
+ }
209
+ function stillCurrent(stamps) {
210
+ for (const [file, was] of stamps) if (stamp(file) !== was) return false;
211
+ return true;
212
+ }
213
+ function head(file) {
214
+ let fd;
215
+ try {
216
+ fd = fs.openSync(file, "r");
217
+ const buf = Buffer.alloc(FILE_HEAD_BYTES);
218
+ const got = fs.readSync(fd, buf, 0, FILE_HEAD_BYTES, 0);
219
+ return { text: buf.subarray(0, got).toString("utf8"), cut: got === FILE_HEAD_BYTES && fs.fstatSync(fd).size > got };
220
+ } catch (err) {
221
+ const code = err.code;
222
+ return { failure: code === "ENOENT" || code === "ENOTDIR" ? "missing" : "unreadable" };
223
+ } finally {
224
+ if (fd !== void 0) fs.closeSync(fd);
225
+ }
226
+ }
227
+ function checkFile(file, scan, place) {
228
+ const lower = file.toLowerCase();
229
+ const json = lower.endsWith(".json");
230
+ if (!json && !lower.endsWith(".md")) return;
231
+ record(scan, file);
232
+ const read = head(file);
233
+ let text;
234
+ let cut;
235
+ if ("failure" in read) {
236
+ if (read.failure === "unreadable") {
237
+ scan.reason = `cannot read ${file}`;
238
+ return;
239
+ }
240
+ const indexed = scan.indexedText?.(file);
241
+ if (indexed === void 0) return;
242
+ if (indexed === null) {
243
+ scan.reason = `cannot read ${file} from the index`;
244
+ return;
245
+ }
246
+ text = indexed.slice(0, FILE_HEAD_BYTES);
247
+ cut = indexed.length > FILE_HEAD_BYTES;
248
+ } else {
249
+ text = read.text;
250
+ cut = read.cut;
251
+ }
252
+ const front = json ? void 0 : frontmatter(text) ?? "";
253
+ const unfinished = cut && (json || OPENS_FRONTMATTER.test(text) && frontmatter(text) === void 0);
254
+ if (front === void 0 ? text.includes("PermissionRequest") : frontmatterAddsRule(front)) scan.reason = `rule source ${file}`;
255
+ else if (unfinished) scan.reason = `cannot scan ${file}: it runs past the first ${FILE_HEAD_BYTES} bytes read`;
256
+ else if (front !== void 0 && place.agents) {
257
+ const name = /^name[ \t]*:(.*)$/m.exec(front)?.[1]?.trim().replace(/^(["'])(.*)\1$/, "$2");
258
+ if (name !== void 0 && name !== "") (place.plugin ? scan.pluginAgents : scan.agents).add(name);
259
+ }
260
+ }
261
+ function linksToDir(full) {
262
+ try {
263
+ return fs.lstatSync(full).isSymbolicLink() && fs.statSync(full).isDirectory();
264
+ } catch {
265
+ return false;
266
+ }
267
+ }
268
+ function scanDir(dir, scan, place) {
269
+ if (scan.reason !== null || !scan.helpers.sourceAllowed(dir)) return;
270
+ record(scan, dir);
271
+ let entries;
272
+ try {
273
+ entries = fs.readdirSync(dir, { withFileTypes: true });
274
+ } catch (err) {
275
+ const code = err.code;
276
+ if (code !== "ENOENT" && code !== "ENOTDIR") scan.reason = `cannot read ${dir}`;
277
+ return;
278
+ }
279
+ for (const entry of entries) {
280
+ if (scan.reason !== null) return;
281
+ if (--scan.budget < 0) {
282
+ scan.reason = "too many files to check";
283
+ return;
284
+ }
285
+ const full = path.join(dir, entry.name);
286
+ let isDir = entry.isDirectory();
287
+ let isFile = entry.isFile();
288
+ if (entry.isSymbolicLink()) {
289
+ try {
290
+ const st = fs.statSync(full);
291
+ isDir = st.isDirectory();
292
+ isFile = st.isFile();
293
+ } catch {
294
+ continue;
295
+ }
296
+ }
297
+ if (isDir && entry.name !== "node_modules" && entry.name !== ".git") {
298
+ if (place.depth >= 32) scan.reason = `too deep under ${dir}`;
299
+ else scanDir(full, scan, { ...place, depth: place.depth + 1, agents: place.agents || entry.name === "agents" });
300
+ } else if (isFile) {
301
+ checkFile(full, scan, place);
302
+ }
303
+ }
304
+ }
305
+ function scanClaudeDir(claudeDir, scan) {
306
+ for (const sub of RULE_DIRS) scanDir(path.join(claudeDir, sub), scan, { depth: 0, agents: sub === "agents", plugin: false });
307
+ }
308
+ function firstWalk(dir, scan) {
309
+ let real;
310
+ try {
311
+ real = fs.realpathSync.native(dir);
312
+ } catch {
313
+ return true;
314
+ }
315
+ const key = process.platform === "win32" ? real.toLowerCase() : real;
316
+ if (scan.walked.has(key)) return false;
317
+ scan.walked.add(key);
318
+ return true;
319
+ }
320
+ function walkForClaudeDirs(dir, scan, depth = 0) {
321
+ if (scan.reason !== null || !scan.helpers.sourceAllowed(dir) || !firstWalk(dir, scan)) return;
322
+ let entries;
323
+ try {
324
+ entries = fs.readdirSync(dir, { withFileTypes: true });
325
+ } catch (err) {
326
+ const code = err.code;
327
+ if (code !== "ENOENT" && code !== "ENOTDIR") scan.reason = `cannot read ${dir}`;
328
+ return;
329
+ }
330
+ for (const entry of entries) {
331
+ if (scan.reason !== null) return;
332
+ if (--scan.budget < 0) {
333
+ scan.reason = "too many files to check";
334
+ return;
335
+ }
336
+ if (entry.name === ".git") continue;
337
+ const full = path.join(dir, entry.name);
338
+ if (!entry.isDirectory() && !(entry.isSymbolicLink() && linksToDir(full))) continue;
339
+ if (entry.name === ".claude") scanClaudeDir(full, scan);
340
+ else if (depth >= 32) scan.reason = `too deep under ${dir}`;
341
+ else walkForClaudeDirs(full, scan, depth + 1);
342
+ }
343
+ }
344
+ function scanGitCheckout(project, scan) {
345
+ const list = (args) => {
346
+ const res = scan.helpers.runGit(["ls-files", "-z", ...args], { cwd: project, timeoutMs: 15e3 });
347
+ return res.exitCode === 0 ? res.stdout.split("\0").filter((entry) => entry !== "") : null;
348
+ };
349
+ const tracked = list(["-s"]);
350
+ const untracked = list(["-o", "--exclude-standard"]);
351
+ const ignored = list(["-o", "-i", "--exclude-standard", "--directory"]);
352
+ if (tracked === null || untracked === null || ignored === null) {
353
+ scan.reason = "cannot list nested skills";
354
+ return;
355
+ }
356
+ stampListedDirs(project, [...tracked.map((record2) => record2.slice(record2.indexOf(" ") + 1)), ...untracked, ...ignored], scan);
357
+ const candidates = [...untracked, ...ignored.filter((rel) => !rel.endsWith("/"))];
358
+ const objects = /* @__PURE__ */ new Map();
359
+ for (const record2 of tracked) {
360
+ const tab = record2.indexOf(" ");
361
+ const rel = record2.slice(tab + 1);
362
+ if (record2.startsWith("120000 ") || RULE_PATH.test(rel)) candidates.push(rel);
363
+ if (RULE_PATH.test(rel)) objects.set(path.join(project, rel), record2.slice(0, tab).split(" ")[1]);
364
+ }
365
+ scan.indexedText = (file) => {
366
+ const object = objects.get(file);
367
+ if (object === void 0) return void 0;
368
+ const res = scan.helpers.runGit(["cat-file", "blob", object], { cwd: project, timeoutMs: 15e3 });
369
+ return res.exitCode === 0 ? res.stdout : null;
370
+ };
371
+ const sorted = [...ignored].sort();
372
+ const ignoredDirs = sorted.filter((rel, i) => rel.endsWith("/") && sorted[i + 1]?.startsWith(rel) !== true && CLAUDE_INSIDE.test(rel));
373
+ for (const rel of [...candidates, ...ignoredDirs]) {
374
+ if (scan.reason !== null) return;
375
+ if (--scan.budget < 0) {
376
+ scan.reason = "too many files to check";
377
+ return;
378
+ }
379
+ const full = path.join(project, rel);
380
+ const place = { depth: 0, agents: AGENT_PATH.test(rel), plugin: false };
381
+ if (rel.endsWith("/") || linksToDir(full)) {
382
+ if (RULE_PATH.test(rel)) scanDir(full, scan, place);
383
+ else if (path.basename(full) === ".claude") scanClaudeDir(full, scan);
384
+ else if (!rel.endsWith("/")) walkForClaudeDirs(full, scan);
385
+ } else if (RULE_PATH.test(rel)) {
386
+ checkFile(full, scan, place);
387
+ }
388
+ }
389
+ }
390
+ function scanFixed(cwd, project, helpers) {
391
+ const scan = newScan(helpers, true);
392
+ const configDir = helpers.configDir();
393
+ const roots = [configDir, ...[cwd, project].flatMap(helpers.selfAndAncestors).map((d) => path.join(d, ".claude")), ...helpers.managedDirs().map((d) => path.join(d, ".claude"))];
394
+ const seen = /* @__PURE__ */ new Set();
395
+ for (const root of roots) {
396
+ const key = process.platform === "win32" ? root.toLowerCase() : root;
397
+ if (seen.has(key)) continue;
398
+ seen.add(key);
399
+ scanClaudeDir(root, scan);
400
+ }
401
+ scanDir(path.join(configDir, "plugins", "cache"), scan, { depth: 0, agents: false, plugin: true });
402
+ return result(scan);
403
+ }
404
+ function gitDirOf(root) {
405
+ const dot = path.join(root, ".git");
406
+ try {
407
+ if (fs.statSync(dot).isDirectory()) return dot;
408
+ const line = fs.readFileSync(dot, "utf8").split("\n").find((l) => l.startsWith("gitdir:"));
409
+ const named = line?.slice("gitdir:".length).trim();
410
+ return named === void 0 || named === "" ? dot : path.resolve(root, named);
411
+ } catch {
412
+ return dot;
413
+ }
414
+ }
415
+ function stampGitState(root, scan) {
416
+ const gitDir = gitDirOf(root);
417
+ for (const name of ["index", "HEAD"]) record(scan, path.join(gitDir, name));
418
+ }
419
+ function stampListedDirs(project, listed, scan) {
420
+ const dirs = /* @__PURE__ */ new Set([project]);
421
+ for (const rel of listed) {
422
+ const parts = rel.split("/").filter((part) => part !== "");
423
+ const claude = parts.indexOf(".claude");
424
+ const add = (from, to) => {
425
+ for (let n = from; n <= to; n++) dirs.add(path.join(project, ...parts.slice(0, n)));
426
+ };
427
+ add(1, Math.min(parts.length - 1, NESTED_STAMP_DEPTH));
428
+ if (claude >= 0) add(claude, parts.length - 1);
429
+ if (dirs.size >= NESTED_STAMP_DIRS) {
430
+ scan.volatile = true;
431
+ break;
432
+ }
433
+ }
434
+ for (const dir of dirs) record(scan, dir);
435
+ }
436
+ function scanNested(project, helpers) {
437
+ const scan = newScan(helpers, true);
438
+ const root = helpers.selfAndAncestors(project).find((d) => fs.existsSync(path.join(d, ".git")));
439
+ if (root !== void 0) {
440
+ stampGitState(root, scan);
441
+ scanGitCheckout(project, scan);
442
+ } else walkForClaudeDirs(project, scan);
443
+ return result(scan);
444
+ }
445
+ function agentReason(agentType, scans) {
446
+ if (agentType === void 0 || BUILTIN_AGENTS.has(agentType)) return null;
447
+ const colon = agentType.lastIndexOf(":");
448
+ const known = colon < 0 ? scans.some((s) => s.agents.has(agentType)) : scans.some((s) => s.pluginAgents.has(agentType.slice(colon + 1)));
449
+ return known ? null : `agent ${agentType} not checked`;
450
+ }
451
+ function hiddenRuleSource(cwd, projectDir, env, helpers, query = {}) {
452
+ const now = query.now ?? Date.now();
453
+ const processKey = processKeyOf(env);
454
+ const processReasonNow = query.filesOnly === true ? null : processReason(env);
455
+ if (processReasonNow !== null) return processReasonNow;
456
+ const here = path.resolve(cwd);
457
+ const project = projectDir !== void 0 && path.isAbsolute(projectDir) ? path.resolve(projectDir) : here;
458
+ const scanKey = `${processKey}:${here}:${project}`;
459
+ if (fixedCache?.key !== scanKey || (fixedCache.reason !== null ? now - fixedCache.at > SCAN_TTL_MS : fixedCache.volatile || !stillCurrent(fixedCache.stamps))) fixedCache = { key: scanKey, at: now, ...scanFixed(here, project, helpers) };
460
+ if (fixedCache.reason !== null) return fixedCache.reason;
461
+ if (nestedCache?.key !== scanKey || now - nestedCache.at > SCAN_TTL_MS || nestedCache.reason === null && (nestedCache.volatile || !stillCurrent(nestedCache.stamps))) nestedCache = { key: scanKey, at: now, ...scanNested(project, helpers) };
462
+ return nestedCache.reason ?? agentReason(query.agentType, [fixedCache, nestedCache]);
463
+ }
464
+ function hiddenRules(helpers) {
465
+ return {
466
+ hidden: (cwd, agentType, filesOnly) => hiddenRuleSource(cwd, process.env["CLAUDE_PROJECT_DIR"], process.env, helpers, { agentType, filesOnly }) !== null,
467
+ lineRules: () => commandLineRuleSource(process.env) !== null,
468
+ prime: (env) => primeProcessReason(env)
469
+ };
470
+ }
471
+ export {
472
+ commandLineRuleSource,
473
+ frontmatterAddsRule,
474
+ hiddenRuleSource,
475
+ hiddenRules,
476
+ primeProcessReason,
477
+ resetHiddenRuleCache,
478
+ stamp
479
+ };
@@ -3,12 +3,13 @@ const require = __cjsRequire(import.meta.url);
3
3
  import {
4
4
  copyFromSharedCache,
5
5
  downloadPinned
6
- } from "./token-goat-chunk-PD5VKH46.mjs";
7
- import "./token-goat-chunk-SMVRN2HU.mjs";
6
+ } from "./token-goat-chunk-AUNGYYQX.mjs";
7
+ import "./token-goat-chunk-2UPZGKKY.mjs";
8
8
  import {
9
9
  loadConfig
10
- } from "./token-goat-chunk-7IN2MKDS.mjs";
11
- import "./token-goat-chunk-U4N3BN2W.mjs";
10
+ } from "./token-goat-chunk-7EZTZOMC.mjs";
11
+ import "./token-goat-chunk-QYHO5CPH.mjs";
12
+ import "./token-goat-chunk-4GBVPH3D.mjs";
12
13
  import {
13
14
  registerReset
14
15
  } from "./token-goat-chunk-YZAAZU2S.mjs";
@@ -16,12 +17,13 @@ import "./token-goat-chunk-IVE6U7KV.mjs";
16
17
  import {
17
18
  atomicWriteText,
18
19
  ensureDirSync
19
- } from "./token-goat-chunk-GOLEOXZP.mjs";
20
+ } from "./token-goat-chunk-HU4TORC5.mjs";
21
+ import "./token-goat-chunk-GGGG7RWB.mjs";
20
22
  import "./token-goat-chunk-AM5V6GSX.mjs";
21
23
  import "./token-goat-chunk-FNFBKLRD.mjs";
22
24
  import {
23
25
  ensureDataDirPrivate
24
- } from "./token-goat-chunk-VES7EL7O.mjs";
26
+ } from "./token-goat-chunk-CO3UYX6G.mjs";
25
27
  import {
26
28
  init_define_import_meta_env
27
29
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -1,18 +1,25 @@
1
1
  import { createRequire as __cjsRequire } from 'node:module';
2
2
  const require = __cjsRequire(import.meta.url);
3
+ import {
4
+ formatCommandError,
5
+ writeCommandFailure
6
+ } from "./token-goat-chunk-CBIQ7WTD.mjs";
3
7
  import {
4
8
  loadConfig
5
- } from "./token-goat-chunk-7IN2MKDS.mjs";
9
+ } from "./token-goat-chunk-7EZTZOMC.mjs";
6
10
  import {
7
11
  ensureDirSync
8
- } from "./token-goat-chunk-GOLEOXZP.mjs";
12
+ } from "./token-goat-chunk-HU4TORC5.mjs";
13
+ import {
14
+ fencedCommand
15
+ } from "./token-goat-chunk-GGGG7RWB.mjs";
9
16
  import {
10
17
  displaySafeJson
11
18
  } from "./token-goat-chunk-FNFBKLRD.mjs";
12
19
  import {
13
20
  VERSION,
14
21
  dataDir
15
- } from "./token-goat-chunk-VES7EL7O.mjs";
22
+ } from "./token-goat-chunk-CO3UYX6G.mjs";
16
23
  import {
17
24
  init_define_import_meta_env
18
25
  } from "./token-goat-chunk-A37V4PBF.mjs";
@@ -102,7 +109,7 @@ function currentUpgradeDecision(status) {
102
109
  }
103
110
  var DEV_CHECKOUT_ADVICE = "git pull && npm run build && token-goat install";
104
111
  function updateAdvice(decision) {
105
- if (decision === "install") return "Run 'token-goat upgrade' to update.";
112
+ if (decision === "install") return "Run `token-goat upgrade` to update.";
106
113
  if (decision === "dev-checkout") return `This token-goat runs from a development checkout. To update it, run: ${DEV_CHECKOUT_ADVICE}`;
107
114
  return null;
108
115
  }
@@ -137,6 +144,8 @@ async function fetchViaHttp(registryUrl, timeoutMs = 3500) {
137
144
  targetUrl,
138
145
  {
139
146
  headers: { "User-Agent": `token-goat/${VERSION} (node/${process.version})` },
147
+ // A fresh connection, never one pooled by the global agent: after npm's blocking spawn the registry may have closed the pooled one, and reusing it fails with ECONNRESET.
148
+ agent: false,
140
149
  timeout: timeoutMs
141
150
  },
142
151
  (res) => {
@@ -247,18 +256,18 @@ async function checkUpdateStatus(timeoutMs = 3500, forceFresh = false) {
247
256
  async function cmdUpgrade(opts = {}, onSyncHooks) {
248
257
  const status = await checkUpdateStatus(3500, true);
249
258
  if (opts.check) {
250
- if (opts.json) {
251
- console.log(displaySafeJson(status, 2));
259
+ const failure = status.error ?? (status.latest ? void 0 : "could not determine the latest version");
260
+ if (failure !== void 0) {
261
+ writeCommandFailure(opts.json === true, { ...status }, [`${failure}.`, `Current version: v${status.current}`]);
252
262
  return;
253
263
  }
254
- if (status.error) {
255
- console.log(`Current version: v${status.current}`);
256
- console.log(`[!] ${status.error}`);
264
+ if (opts.json) {
265
+ console.log(displaySafeJson(status, 2));
257
266
  return;
258
267
  }
259
268
  if (status.updateAvailable && status.latest) {
260
269
  console.log(`Update available: v${status.current} -> v${status.latest}`);
261
- console.log(`Run 'token-goat upgrade' to update.`);
270
+ console.log(`Run \`token-goat upgrade\` to update.`);
262
271
  } else {
263
272
  console.log(`token-goat is up to date (v${status.current})`);
264
273
  }
@@ -267,11 +276,11 @@ async function cmdUpgrade(opts = {}, onSyncHooks) {
267
276
  const decision = currentUpgradeDecision(status);
268
277
  switch (decision) {
269
278
  case "offline":
270
- console.error(`token-goat: network.offline is set, so no update check was made and nothing was installed. Unset it (or TOKEN_GOAT_OFFLINE) to upgrade.`);
279
+ console.error(formatCommandError("network.offline is set, so no update check was made and nothing was installed. Unset it (or TOKEN_GOAT_OFFLINE) to upgrade."));
271
280
  process.exitCode = 1;
272
281
  return;
273
282
  case "unreachable":
274
- console.error(`token-goat: ${status.error ?? "could not determine the latest version"}. Nothing was installed.`);
283
+ console.error(formatCommandError(`${status.error ?? "could not determine the latest version"}. Nothing was installed.`));
275
284
  process.exitCode = 1;
276
285
  return;
277
286
  case "up-to-date":
@@ -288,7 +297,7 @@ async function cmdUpgrade(opts = {}, onSyncHooks) {
288
297
  console.log(`Upgrading token-goat v${status.current} -> v${status.latest}...`);
289
298
  const outcome = await performUpgrade(onSyncHooks);
290
299
  if (!outcome.ok) {
291
- console.error(`token-goat: ${outcome.message}`);
300
+ console.error(formatCommandError(outcome.message));
292
301
  process.exitCode = 1;
293
302
  return;
294
303
  }
@@ -296,35 +305,43 @@ async function cmdUpgrade(opts = {}, onSyncHooks) {
296
305
  }
297
306
  var MANUAL_INSTALL = "npm install -g token-goat@latest";
298
307
  async function performUpgrade(onSyncHooks, npm = hostNpm()) {
299
- if (!npm) return { ok: false, message: `npm was not found next to this Node.js, so token-goat could not upgrade itself. Run '${MANUAL_INSTALL}' yourself.` };
308
+ if (!npm) return { ok: false, message: `npm was not found next to this Node.js, so token-goat could not upgrade itself. Run ${fencedCommand(MANUAL_INSTALL)} yourself.` };
309
+ let stoppedPid = [];
300
310
  try {
301
- const { stopWorker } = await import("./token-goat-chunk-KQNZDCBD.mjs");
311
+ const { stopWorker, readPidFile } = await import("./token-goat-chunk-NSNSPPBG.mjs");
302
312
  const { queryServers } = await import("./token-goat-hook-client.mjs");
303
313
  await queryServers("stop");
304
- stopWorker();
314
+ const tracked = readPidFile(dataDir());
315
+ if (stopWorker() && tracked !== null) stoppedPid = [tracked];
316
+ } catch {
317
+ }
318
+ try {
319
+ const { retireStrayResidents, describeRetirement, UPGRADE_RESIDENT_KINDS } = await import("./token-goat-chunk-TAUZ4OFS.mjs");
320
+ const note = describeRetirement(await retireStrayResidents({ kinds: UPGRADE_RESIDENT_KINDS, skip: stoppedPid }));
321
+ if (note !== null) console.log(note);
305
322
  } catch {
306
323
  }
307
324
  const install = spawnSync(npm.file, [...npm.prefix, "install", "-g", "token-goat@latest"], { stdio: "inherit", windowsHide: true });
308
325
  if (install.status !== 0) {
309
326
  const why = install.error ? install.error.message : `exit code ${install.status ?? "unknown"}`;
310
- return { ok: false, message: `npm install failed (${why}). If npm reported EPERM or EBUSY, another program still has token-goat's files open: close running agent sessions and run '${MANUAL_INSTALL}'.` };
327
+ return { ok: false, message: `npm install failed (${why}). If npm reported EPERM or EBUSY, another program still has token-goat's files open: close running agent sessions and run ${fencedCommand(MANUAL_INSTALL)}.` };
311
328
  }
312
329
  console.log(`Syncing token-goat hooks and integration manifests...`);
313
330
  const launcher = installedLauncher(npm);
314
331
  if (launcher) {
315
332
  const sync = spawnSync(process.execPath, [launcher, "install"], { stdio: "inherit", windowsHide: true });
316
- if (sync.status !== 0) return { ok: false, message: `the new version installed, but 'token-goat install' failed (exit code ${sync.status ?? "unknown"}). Run 'token-goat install' to finish.` };
333
+ if (sync.status !== 0) return { ok: false, message: `the new version installed, but \`token-goat install\` failed (exit code ${sync.status ?? "unknown"}). Run \`token-goat install\` to finish.` };
317
334
  return { ok: true };
318
335
  }
319
336
  try {
320
337
  if (onSyncHooks) await onSyncHooks();
321
338
  } catch (e) {
322
- return { ok: false, message: `the new version installed, but syncing hooks failed (${e instanceof Error ? e.message : String(e)}). Run 'token-goat install' to finish.` };
339
+ return { ok: false, message: `the new version installed, but syncing hooks failed (${e instanceof Error ? e.message : String(e)}). Run \`token-goat install\` to finish.` };
323
340
  }
324
341
  return { ok: true };
325
342
  }
326
343
  function installedLauncher(npm) {
327
- const res = spawnSync(npm.file, [...npm.prefix, "root", "-g"], { encoding: "utf8", timeout: 1e4, stdio: ["ignore", "pipe", "ignore"], windowsHide: true });
344
+ const res = spawnSync(npm.file, [...npm.prefix, "root", "-g"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], windowsHide: true });
328
345
  const root = res.status === 0 && typeof res.stdout === "string" ? res.stdout.trim() : "";
329
346
  if (!root) return null;
330
347
  const launcher = path.join(root, "token-goat", "dist", "token-goat.mjs");