@eyeauras/insight-cli 0.2.0 → 0.2.1

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 (384) hide show
  1. package/.cli-package-build.json +1 -1
  2. package/README.md +25 -0
  3. package/SKILL.md +38 -54
  4. package/dist/src/binary.d.ts +3 -0
  5. package/dist/src/binary.js +74 -0
  6. package/dist/src/capture.d.ts +3 -0
  7. package/dist/src/capture.js +220 -0
  8. package/dist/src/cli.js +57 -12
  9. package/dist/src/contexts.d.ts +5 -0
  10. package/dist/src/contexts.js +42 -16
  11. package/dist/src/debugger-caller.d.ts +17 -0
  12. package/dist/src/debugger-caller.js +129 -0
  13. package/dist/src/debugger-launch.d.ts +2 -0
  14. package/dist/src/debugger-launch.js +17 -0
  15. package/dist/src/debugger-results.d.ts +1 -0
  16. package/dist/src/debugger-results.js +8 -0
  17. package/dist/src/debugger-supervisor.js +56 -13
  18. package/dist/src/debugger.js +16 -7
  19. package/dist/src/die.d.ts +12 -0
  20. package/dist/src/die.js +127 -0
  21. package/dist/src/dnspy-runtime.d.ts +8 -0
  22. package/dist/src/dnspy-runtime.js +46 -0
  23. package/dist/src/dnspy.d.ts +22 -0
  24. package/dist/src/dnspy.js +160 -0
  25. package/dist/src/dotnet-diagnostics.d.ts +13 -0
  26. package/dist/src/dotnet-diagnostics.js +101 -0
  27. package/dist/src/frida-worker.d.ts +1 -0
  28. package/dist/src/frida-worker.js +125 -0
  29. package/dist/src/frida.d.ts +16 -0
  30. package/dist/src/frida.js +125 -0
  31. package/dist/src/ghidra-debugger-runtime.d.ts +7 -0
  32. package/dist/src/ghidra-debugger-runtime.js +31 -0
  33. package/dist/src/ghidra-processes.d.ts +6 -0
  34. package/dist/src/ghidra-processes.js +121 -0
  35. package/dist/src/ghidra.js +6 -6
  36. package/dist/src/ilspy.d.ts +7 -0
  37. package/dist/src/ilspy.js +122 -0
  38. package/dist/src/lldb.d.ts +10 -0
  39. package/dist/src/lldb.js +99 -0
  40. package/dist/src/llvm.d.ts +6 -0
  41. package/dist/src/llvm.js +133 -0
  42. package/dist/src/managed-heap.d.ts +4 -0
  43. package/dist/src/managed-heap.js +73 -0
  44. package/dist/src/managed-metadata.d.ts +11 -0
  45. package/dist/src/managed-metadata.js +66 -0
  46. package/dist/src/mitmproxy.d.ts +55 -0
  47. package/dist/src/mitmproxy.js +172 -0
  48. package/dist/src/native-inputs.d.ts +3 -2
  49. package/dist/src/native-inputs.js +9 -4
  50. package/dist/src/package-version.d.ts +1 -0
  51. package/dist/src/package-version.js +3 -0
  52. package/dist/src/procmon-config.d.ts +2 -0
  53. package/dist/src/procmon-config.js +15 -0
  54. package/dist/src/procmon-events.d.ts +13 -0
  55. package/dist/src/procmon-events.js +82 -0
  56. package/dist/src/procmon.d.ts +4 -0
  57. package/dist/src/procmon.js +107 -0
  58. package/dist/src/research.d.ts +11 -2
  59. package/dist/src/research.js +5 -3
  60. package/dist/src/runtime-catalog.d.ts +5 -10
  61. package/dist/src/runtime-catalog.js +4 -5
  62. package/dist/src/runtime-manager.d.ts +27 -3
  63. package/dist/src/runtime-manager.js +100 -159
  64. package/dist/src/runtime-selection.js +21 -4
  65. package/dist/src/server.d.ts +13 -0
  66. package/dist/src/server.js +21 -45
  67. package/dist/src/sevenzip.d.ts +15 -0
  68. package/dist/src/sevenzip.js +119 -0
  69. package/dist/src/strace.d.ts +10 -0
  70. package/dist/src/strace.js +71 -0
  71. package/dist/src/text-window.d.ts +11 -0
  72. package/dist/src/text-window.js +6 -0
  73. package/dist/src/tool-runtime/archives.d.ts +10 -0
  74. package/dist/src/{runtime-archives.js → tool-runtime/archives.js} +91 -24
  75. package/dist/src/tool-runtime/catalog.d.ts +3 -0
  76. package/dist/src/tool-runtime/catalog.js +13 -0
  77. package/dist/src/tool-runtime/commands.d.ts +9 -0
  78. package/dist/src/tool-runtime/commands.js +39 -0
  79. package/dist/src/tool-runtime/deadline.d.ts +11 -0
  80. package/dist/src/tool-runtime/deadline.js +32 -0
  81. package/dist/src/tool-runtime/definition.d.ts +73 -0
  82. package/dist/src/tool-runtime/definition.js +49 -0
  83. package/dist/src/tool-runtime/dotnet.d.ts +4 -0
  84. package/dist/src/tool-runtime/dotnet.js +22 -0
  85. package/dist/src/tool-runtime/identity.d.ts +6 -0
  86. package/dist/src/tool-runtime/identity.js +50 -0
  87. package/dist/src/tool-runtime/installer.d.ts +101 -0
  88. package/dist/src/tool-runtime/installer.js +180 -0
  89. package/dist/src/tool-runtime/launch-worker.d.ts +1 -0
  90. package/dist/src/tool-runtime/launch-worker.js +58 -0
  91. package/dist/src/tool-runtime/run.d.ts +51 -0
  92. package/dist/src/tool-runtime/run.js +159 -0
  93. package/dist/src/tool-runtime/store.d.ts +15 -0
  94. package/dist/src/tool-runtime/store.js +219 -0
  95. package/dist/src/tool-runtime/supervisor.d.ts +57 -0
  96. package/dist/src/tool-runtime/supervisor.js +266 -0
  97. package/dist/src/tool-runtime/windows-job.d.ts +22 -0
  98. package/dist/src/tool-runtime/windows-job.js +43 -0
  99. package/dist/src/toolbox.d.ts +84 -0
  100. package/dist/src/toolbox.js +35 -0
  101. package/dist/src/tshark.d.ts +23 -0
  102. package/dist/src/tshark.js +174 -0
  103. package/dist/src/windbg.d.ts +14 -0
  104. package/dist/src/windbg.js +119 -0
  105. package/dist/src/workspace.d.ts +1 -0
  106. package/dist/src/workspace.js +6 -0
  107. package/package.json +5 -4
  108. package/references/agent-execution.md +36 -0
  109. package/references/agent-setup.md +61 -0
  110. package/references/artifacts.md +5 -0
  111. package/references/debugger.md +22 -0
  112. package/references/ilspy.md +33 -0
  113. package/references/managed-runtime.md +48 -7
  114. package/references/native/InsightPythonWheels.java +283 -2
  115. package/references/native/InsightTraceState.java +28 -13
  116. package/references/setup.md +2 -1
  117. package/runtime/managed/insight-heap/Azure.Core.dll +0 -0
  118. package/runtime/managed/insight-heap/Azure.Identity.dll +0 -0
  119. package/runtime/managed/insight-heap/Insight.Heap.csproj +1 -0
  120. package/runtime/managed/insight-heap/Insight.Heap.deps.json +391 -0
  121. package/runtime/managed/insight-heap/Insight.Heap.dll +0 -0
  122. package/runtime/managed/insight-heap/Insight.Heap.runtimeconfig.json +13 -0
  123. package/runtime/managed/insight-heap/Microsoft.Bcl.AsyncInterfaces.dll +0 -0
  124. package/runtime/managed/insight-heap/Microsoft.Diagnostics.NETCore.Client.dll +0 -0
  125. package/runtime/managed/insight-heap/Microsoft.Diagnostics.Runtime.dll +0 -0
  126. package/runtime/managed/insight-heap/Microsoft.Extensions.Configuration.Abstractions.dll +0 -0
  127. package/runtime/managed/insight-heap/Microsoft.Extensions.DependencyInjection.Abstractions.dll +0 -0
  128. package/runtime/managed/insight-heap/Microsoft.Extensions.Diagnostics.Abstractions.dll +0 -0
  129. package/runtime/managed/insight-heap/Microsoft.Extensions.FileProviders.Abstractions.dll +0 -0
  130. package/runtime/managed/insight-heap/Microsoft.Extensions.Hosting.Abstractions.dll +0 -0
  131. package/runtime/managed/insight-heap/Microsoft.Extensions.Logging.Abstractions.dll +0 -0
  132. package/runtime/managed/insight-heap/Microsoft.Extensions.Options.dll +0 -0
  133. package/runtime/managed/insight-heap/Microsoft.Extensions.Primitives.dll +0 -0
  134. package/runtime/managed/insight-heap/Microsoft.Identity.Client.Extensions.Msal.dll +0 -0
  135. package/runtime/managed/insight-heap/Microsoft.Identity.Client.dll +0 -0
  136. package/runtime/managed/insight-heap/Microsoft.IdentityModel.Abstractions.dll +0 -0
  137. package/runtime/managed/insight-heap/Microsoft.Security.AntiSSRF.dll +0 -0
  138. package/runtime/managed/insight-heap/NuGet.Config +1 -0
  139. package/runtime/managed/insight-heap/Program.cs +20 -0
  140. package/runtime/managed/insight-heap/README.md +16 -0
  141. package/runtime/managed/insight-heap/System.ClientModel.dll +0 -0
  142. package/runtime/managed/insight-heap/System.Memory.Data.dll +0 -0
  143. package/runtime/managed/insight-heap/System.Security.Cryptography.ProtectedData.dll +0 -0
  144. package/runtime/managed/insight-heap/dependencies.json +436 -0
  145. package/runtime/managed/insight-heap/notices/Azure.Core-LICENSE.txt +21 -0
  146. package/runtime/managed/insight-heap/notices/Azure.Identity-LICENSE.txt +21 -0
  147. package/runtime/managed/insight-heap/notices/Microsoft.Bcl.AsyncInterfaces-LICENSE.txt +23 -0
  148. package/runtime/managed/insight-heap/notices/Microsoft.Bcl.AsyncInterfaces-THIRD-PARTY-NOTICES.TXT +1418 -0
  149. package/runtime/managed/insight-heap/notices/Microsoft.Diagnostics.NETCore.Client-LICENSE.txt +23 -0
  150. package/runtime/managed/insight-heap/notices/Microsoft.Diagnostics.Runtime-LICENSE.txt +23 -0
  151. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Configuration.Abstractions-LICENSE.txt +23 -0
  152. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Configuration.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  153. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.DependencyInjection.Abstractions-LICENSE.txt +23 -0
  154. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.DependencyInjection.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  155. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Diagnostics.Abstractions-LICENSE.txt +23 -0
  156. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Diagnostics.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  157. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.FileProviders.Abstractions-LICENSE.txt +23 -0
  158. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.FileProviders.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  159. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Hosting.Abstractions-LICENSE.txt +23 -0
  160. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Hosting.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  161. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Logging.Abstractions-LICENSE.txt +23 -0
  162. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Logging.Abstractions-THIRD-PARTY-NOTICES.TXT +1418 -0
  163. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Options-LICENSE.txt +23 -0
  164. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Options-THIRD-PARTY-NOTICES.TXT +1418 -0
  165. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Primitives-LICENSE.txt +23 -0
  166. package/runtime/managed/insight-heap/notices/Microsoft.Extensions.Primitives-THIRD-PARTY-NOTICES.TXT +1418 -0
  167. package/runtime/managed/insight-heap/notices/Microsoft.Identity.Client-LICENSE.txt +21 -0
  168. package/runtime/managed/insight-heap/notices/Microsoft.Identity.Client.Extensions.Msal-LICENSE.txt +21 -0
  169. package/runtime/managed/insight-heap/notices/Microsoft.IdentityModel.Abstractions-LICENSE.txt +21 -0
  170. package/runtime/managed/insight-heap/notices/Microsoft.Security.AntiSSRF-LICENSE.txt +21 -0
  171. package/runtime/managed/insight-heap/notices/System.ClientModel-LICENSE.txt +21 -0
  172. package/runtime/managed/insight-heap/notices/System.Memory.Data-LICENSE.txt +23 -0
  173. package/runtime/managed/insight-heap/notices/System.Memory.Data-THIRD-PARTY-NOTICES.TXT +1418 -0
  174. package/runtime/managed/insight-heap/notices/System.Security.Cryptography.ProtectedData-LICENSE.TXT +23 -0
  175. package/runtime/managed/insight-heap/notices/System.Security.Cryptography.ProtectedData-THIRD-PARTY-NOTICES.TXT +309 -0
  176. package/runtime/managed/insight-heap/packages.lock.json +165 -0
  177. package/runtime/managed/insight-heap/provenance.json +146 -0
  178. package/runtime/managed/insight-heap/runtimes/win/lib/netstandard2.0/System.Security.Cryptography.ProtectedData.dll +0 -0
  179. package/runtime/managed/insight-managed/Insight.Managed.csproj +4 -0
  180. package/runtime/managed/insight-managed/Insight.Managed.deps.json +41 -0
  181. package/runtime/managed/insight-managed/Insight.Managed.dll +0 -0
  182. package/runtime/managed/insight-managed/Insight.Managed.runtimeconfig.json +13 -0
  183. package/runtime/managed/insight-managed/LICENSE.dnlib.txt +20 -0
  184. package/runtime/managed/insight-managed/NuGet.Config +1 -0
  185. package/runtime/managed/insight-managed/Program.cs +31 -0
  186. package/runtime/managed/insight-managed/README.md +16 -0
  187. package/runtime/managed/insight-managed/dnlib.dll +0 -0
  188. package/runtime/managed/insight-managed/packages.lock.json +13 -0
  189. package/runtime/managed/insight-managed/provenance.json +40 -0
  190. package/runtime/native/binary/README.md +22 -0
  191. package/runtime/native/binary/dependencies.json +166 -0
  192. package/runtime/native/binary/helper.cpp +44 -0
  193. package/runtime/native/binary/insight-binary-darwin-arm64 +0 -0
  194. package/runtime/native/binary/notices/Catch2-3.12.0--Catch2-3.12.0__LICENSE.txt +23 -0
  195. package/runtime/native/binary/notices/LIEF-LICENSE.txt +202 -0
  196. package/runtime/native/binary/notices/LIEF-attribution.txt +37 -0
  197. package/runtime/native/binary/notices/Melkor_ELF_Fuzzer-ac2495b--elf_fuzzer-master__LICENSE.txt +674 -0
  198. package/runtime/native/binary/notices/expected-1.3.1--expected-1.3.1__COPYING +121 -0
  199. package/runtime/native/binary/notices/frozen-61dce5a--frozen-61dce5ae18ca59931e27675c468e64118aba8744__AUTHORS +3 -0
  200. package/runtime/native/binary/notices/frozen-61dce5a--frozen-61dce5ae18ca59931e27675c468e64118aba8744__LICENSE +202 -0
  201. package/runtime/native/binary/notices/json-LICENSE.MIT +21 -0
  202. package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--LICENSE +553 -0
  203. package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--framework__LICENSE +553 -0
  204. package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--tf-psa-crypto__LICENSE +552 -0
  205. package/runtime/native/binary/notices/mbedtls-4.0.0.r0.gec4044008d--tf-psa-crypto__framework__LICENSE +553 -0
  206. package/runtime/native/binary/notices/nanobind-2.13.0.r18.g4db9ed3f--LICENSE +26 -0
  207. package/runtime/native/binary/notices/nanobind-2.13.0.r18.g4db9ed3f--ext__robin_map__LICENSE +21 -0
  208. package/runtime/native/binary/notices/span-LICENSE_1_0.txt +23 -0
  209. package/runtime/native/binary/notices/span-attribution.txt +11 -0
  210. package/runtime/native/binary/notices/spdlog-1.17.0--spdlog-1.17.0__LICENSE +25 -0
  211. package/runtime/native/binary/notices/utfcpp-4.0.9--utfcpp-4.0.9__LICENSE +23 -0
  212. package/runtime/native/binary/provenance.json +48 -0
  213. package/runtime/native/child-deadline-linux-x64 +0 -0
  214. package/runtime/native/child-deadline-linux.c +24 -0
  215. package/runtime/native/child-deadline-linux.provenance.json +17 -0
  216. package/runtime/native/deadline-alarm-darwin-universal.dylib +0 -0
  217. package/runtime/native/deadline-alarm.c +33 -0
  218. package/runtime/native/deadline-alarm.provenance.json +22 -0
  219. package/runtime/native/deadline-exec-darwin-arm64 +0 -0
  220. package/runtime/native/deadline-exec.c +24 -0
  221. package/runtime/native/deadline-exec.provenance.json +17 -0
  222. package/runtime/native/dnspy-extension/Bridge.cs +58 -0
  223. package/runtime/native/dnspy-extension/Insight.DnSpy.csproj +13 -0
  224. package/runtime/native/dnspy-extension/Insight.DnSpy.x.dll +0 -0
  225. package/runtime/native/dnspy-extension/NuGet.Config +1 -0
  226. package/runtime/native/dnspy-extension/UNICODE-LOADER.md +26 -0
  227. package/runtime/native/dnspy-extension/packages.lock.json +6 -0
  228. package/runtime/native/dnspy-extension/provenance.json +27 -0
  229. package/runtime/native/dnspy-extension/upstream-public-build.snk +0 -0
  230. package/runtime/native/dnspy-extension/vendor-files.json +4341 -0
  231. package/runtime/native/file-version.ps1 +7 -0
  232. package/runtime/native/insight-registry-win-x64.dll +0 -0
  233. package/runtime/native/mitmproxy/bridge.py +180 -0
  234. package/runtime/native/mitmproxy/notices.json +476 -0
  235. package/runtime/native/sources/detours-LICENSE.md +23 -0
  236. package/runtime/native/sources/detours-e4bfd6b.tar.gz +0 -0
  237. package/runtime/native/sources/detours-provenance.json +10 -0
  238. package/runtime/native/tshark-layout.json +2247 -0
  239. package/runtime/native/windows-job/DirectoryAlias.cs +24 -0
  240. package/runtime/native/windows-job/Insight.WindowsJob.csproj +1 -0
  241. package/runtime/native/windows-job/Insight.WindowsJob.dll +0 -0
  242. package/runtime/native/windows-job/NuGet.Config +1 -0
  243. package/runtime/native/windows-job/OwnedJob.cs +79 -0
  244. package/runtime/native/windows-job/RegistryRedirect.cs +45 -0
  245. package/runtime/native/windows-job/packages.lock.json +21 -0
  246. package/runtime/native/windows-job/provenance.json +16 -0
  247. package/runtime/native/windows-job/windows-job.ps1 +8 -0
  248. package/runtime/native/windows-registry.c +21 -0
  249. package/runtime/native/windows-registry.def +3 -0
  250. package/runtime/native/windows-registry.provenance.json +14 -0
  251. package/runtime/notices/diagnostics-10.0.750501.txt +23 -0
  252. package/runtime/tool-catalog.json +290 -0
  253. package/runtime/toolbox.json +1401 -0
  254. package/skill-bundle/insight-artifacts/SKILL.md +30 -0
  255. package/skill-bundle/insight-artifacts/references/agent-execution.md +36 -0
  256. package/skill-bundle/insight-artifacts/references/artifacts.md +52 -0
  257. package/skill-bundle/insight-binary/SKILL.md +46 -0
  258. package/skill-bundle/insight-binary/references/agent-execution.md +36 -0
  259. package/skill-bundle/insight-capture/SKILL.md +56 -0
  260. package/skill-bundle/insight-capture/references/agent-execution.md +36 -0
  261. package/skill-bundle/insight-cli/SKILL.md +42 -0
  262. package/skill-bundle/insight-cli/references/agent-execution.md +36 -0
  263. package/skill-bundle/insight-cli/references/agent-setup.md +61 -0
  264. package/skill-bundle/insight-die/SKILL.md +49 -0
  265. package/skill-bundle/insight-die/references/agent-execution.md +36 -0
  266. package/skill-bundle/insight-dnspy/SKILL.md +65 -0
  267. package/skill-bundle/insight-dnspy/references/agent-execution.md +36 -0
  268. package/skill-bundle/insight-dotnet-dump/SKILL.md +46 -0
  269. package/skill-bundle/insight-dotnet-dump/references/agent-execution.md +36 -0
  270. package/skill-bundle/insight-dotnet-stack/SKILL.md +39 -0
  271. package/skill-bundle/insight-dotnet-stack/references/agent-execution.md +36 -0
  272. package/skill-bundle/insight-dotnet-trace/SKILL.md +45 -0
  273. package/skill-bundle/insight-dotnet-trace/references/agent-execution.md +36 -0
  274. package/skill-bundle/insight-frida/SKILL.md +67 -0
  275. package/skill-bundle/insight-frida/references/agent-execution.md +36 -0
  276. package/skill-bundle/insight-ghidra/SKILL.md +91 -0
  277. package/skill-bundle/insight-ghidra/references/administration.md +34 -0
  278. package/skill-bundle/insight-ghidra/references/agent-execution.md +36 -0
  279. package/skill-bundle/insight-ghidra/references/archive.md +32 -0
  280. package/skill-bundle/insight-ghidra/references/artifacts.md +52 -0
  281. package/skill-bundle/insight-ghidra/references/debugger.md +62 -0
  282. package/skill-bundle/insight-ghidra/references/extensions-and-sync.md +124 -0
  283. package/skill-bundle/insight-ghidra/references/managed-runtime.md +157 -0
  284. package/skill-bundle/insight-ghidra/references/native-workflows.md +112 -0
  285. package/skill-bundle/insight-ghidra/references/query-semantics.md +96 -0
  286. package/skill-bundle/insight-ghidra/references/recovery.md +53 -0
  287. package/skill-bundle/insight-ghidra/references/research.md +101 -0
  288. package/skill-bundle/insight-ghidra/references/setup.md +50 -0
  289. package/skill-bundle/insight-ilspy/SKILL.md +45 -0
  290. package/skill-bundle/insight-ilspy/references/agent-execution.md +36 -0
  291. package/skill-bundle/insight-ilspy/references/ilspy.md +33 -0
  292. package/skill-bundle/insight-interop/SKILL.md +54 -0
  293. package/skill-bundle/insight-interop/references/agent-execution.md +36 -0
  294. package/skill-bundle/insight-lldb/SKILL.md +54 -0
  295. package/skill-bundle/insight-lldb/references/agent-execution.md +36 -0
  296. package/skill-bundle/insight-llvm/SKILL.md +56 -0
  297. package/skill-bundle/insight-llvm/references/agent-execution.md +36 -0
  298. package/skill-bundle/insight-managed-heap/SKILL.md +43 -0
  299. package/skill-bundle/insight-managed-heap/references/agent-execution.md +36 -0
  300. package/skill-bundle/insight-managed-metadata/SKILL.md +52 -0
  301. package/skill-bundle/insight-managed-metadata/references/agent-execution.md +36 -0
  302. package/skill-bundle/insight-mitmproxy/SKILL.md +62 -0
  303. package/skill-bundle/insight-mitmproxy/references/agent-execution.md +36 -0
  304. package/skill-bundle/insight-overview/SKILL.md +79 -0
  305. package/skill-bundle/insight-overview/references/agent-execution.md +36 -0
  306. package/skill-bundle/insight-procmon/SKILL.md +49 -0
  307. package/skill-bundle/insight-procmon/references/agent-execution.md +36 -0
  308. package/skill-bundle/insight-re/SKILL.md +121 -0
  309. package/skill-bundle/insight-re/references/agent-execution.md +36 -0
  310. package/skill-bundle/insight-re/references/artifacts.md +52 -0
  311. package/skill-bundle/insight-re/references/recovery.md +53 -0
  312. package/skill-bundle/insight-sevenzip/SKILL.md +42 -0
  313. package/skill-bundle/insight-sevenzip/references/agent-execution.md +36 -0
  314. package/skill-bundle/insight-strace/SKILL.md +46 -0
  315. package/skill-bundle/insight-strace/references/agent-execution.md +36 -0
  316. package/skill-bundle/insight-tshark/SKILL.md +49 -0
  317. package/skill-bundle/insight-tshark/references/agent-execution.md +36 -0
  318. package/skill-bundle/insight-windbg/SKILL.md +46 -0
  319. package/skill-bundle/insight-windbg/references/agent-execution.md +36 -0
  320. package/skill-bundle/manifest.json +32 -0
  321. package/skills/insight-artifacts/SKILL.md +30 -0
  322. package/skills/insight-artifacts/references/agent-execution.md +36 -0
  323. package/skills/insight-artifacts/references/artifacts.md +52 -0
  324. package/skills/insight-binary/SKILL.md +46 -0
  325. package/skills/insight-binary/references/agent-execution.md +36 -0
  326. package/skills/insight-capture/SKILL.md +56 -0
  327. package/skills/insight-capture/references/agent-execution.md +36 -0
  328. package/skills/insight-die/SKILL.md +49 -0
  329. package/skills/insight-die/references/agent-execution.md +36 -0
  330. package/skills/insight-dnspy/SKILL.md +65 -0
  331. package/skills/insight-dnspy/references/agent-execution.md +36 -0
  332. package/skills/insight-dotnet-dump/SKILL.md +46 -0
  333. package/skills/insight-dotnet-dump/references/agent-execution.md +36 -0
  334. package/skills/insight-dotnet-stack/SKILL.md +39 -0
  335. package/skills/insight-dotnet-stack/references/agent-execution.md +36 -0
  336. package/skills/insight-dotnet-trace/SKILL.md +45 -0
  337. package/skills/insight-dotnet-trace/references/agent-execution.md +36 -0
  338. package/skills/insight-frida/SKILL.md +67 -0
  339. package/skills/insight-frida/references/agent-execution.md +36 -0
  340. package/skills/insight-ghidra/SKILL.md +91 -0
  341. package/skills/insight-ghidra/references/administration.md +34 -0
  342. package/skills/insight-ghidra/references/agent-execution.md +36 -0
  343. package/skills/insight-ghidra/references/archive.md +32 -0
  344. package/skills/insight-ghidra/references/artifacts.md +52 -0
  345. package/skills/insight-ghidra/references/debugger.md +62 -0
  346. package/skills/insight-ghidra/references/extensions-and-sync.md +124 -0
  347. package/skills/insight-ghidra/references/managed-runtime.md +157 -0
  348. package/skills/insight-ghidra/references/native-workflows.md +112 -0
  349. package/skills/insight-ghidra/references/query-semantics.md +96 -0
  350. package/skills/insight-ghidra/references/recovery.md +53 -0
  351. package/skills/insight-ghidra/references/research.md +101 -0
  352. package/skills/insight-ghidra/references/setup.md +50 -0
  353. package/skills/insight-ilspy/SKILL.md +45 -0
  354. package/skills/insight-ilspy/references/agent-execution.md +36 -0
  355. package/skills/insight-ilspy/references/ilspy.md +33 -0
  356. package/skills/insight-interop/SKILL.md +54 -0
  357. package/skills/insight-interop/references/agent-execution.md +36 -0
  358. package/skills/insight-lldb/SKILL.md +54 -0
  359. package/skills/insight-lldb/references/agent-execution.md +36 -0
  360. package/skills/insight-llvm/SKILL.md +56 -0
  361. package/skills/insight-llvm/references/agent-execution.md +36 -0
  362. package/skills/insight-managed-heap/SKILL.md +43 -0
  363. package/skills/insight-managed-heap/references/agent-execution.md +36 -0
  364. package/skills/insight-managed-metadata/SKILL.md +52 -0
  365. package/skills/insight-managed-metadata/references/agent-execution.md +36 -0
  366. package/skills/insight-mitmproxy/SKILL.md +62 -0
  367. package/skills/insight-mitmproxy/references/agent-execution.md +36 -0
  368. package/skills/insight-overview/SKILL.md +79 -0
  369. package/skills/insight-overview/references/agent-execution.md +36 -0
  370. package/skills/insight-procmon/SKILL.md +49 -0
  371. package/skills/insight-procmon/references/agent-execution.md +36 -0
  372. package/skills/insight-re/SKILL.md +22 -9
  373. package/skills/insight-re/references/agent-execution.md +36 -0
  374. package/skills/insight-re/references/artifacts.md +52 -0
  375. package/skills/insight-re/references/recovery.md +53 -0
  376. package/skills/insight-sevenzip/SKILL.md +42 -0
  377. package/skills/insight-sevenzip/references/agent-execution.md +36 -0
  378. package/skills/insight-strace/SKILL.md +46 -0
  379. package/skills/insight-strace/references/agent-execution.md +36 -0
  380. package/skills/insight-tshark/SKILL.md +49 -0
  381. package/skills/insight-tshark/references/agent-execution.md +36 -0
  382. package/skills/insight-windbg/SKILL.md +46 -0
  383. package/skills/insight-windbg/references/agent-execution.md +36 -0
  384. package/dist/src/runtime-archives.d.ts +0 -5
@@ -1 +1 @@
1
- {"version":1,"artifact":"e6afb01edf053fe9b2087f5cc2ca38dd13cb0587a804ebbb1d39c4e5f433c6a3"}
1
+ {"version":1,"artifact":"b65915991d87f45608bceba8cc7afa48b2e04f292149acf604aaf91ec2d2d6ba"}
package/README.md CHANGED
@@ -19,8 +19,31 @@ The pinned Factory IPC runtime is a normal npm dependency fetched from an immuta
19
19
  GitHub tarball URL; installation therefore needs npm registry and GitHub access.
20
20
  Use `insight-cli ghidra install` to deliver the pinned Ghidra/JDK/native/server runtime.
21
21
  External Ghidra launchers and Java paths are also supported.
22
+ `insight-cli ilspy install` delivers ILSpy and its private .NET runtime for managed-code
23
+ research. Tool downloads use pinned assets retained in our GitHub Releases.
24
+ Use `insight-cli tools processes` to inspect owned executions across tools.
22
25
  Help, skill discovery and saving ordinary files do not need Ghidra or Java.
23
26
 
27
+ Downloading a tool does not expose it in an agent's tool list. Connect the packaged skills
28
+ to your agent host, or explicitly give the agent the path returned by `insight-cli skill
29
+ insight-re --json`. See [agent setup](references/agent-setup.md) for tested project-local
30
+ Codex setup and a practical usability check. Installation leaves agent settings unchanged.
31
+
32
+ ## Discover the toolbox
33
+
34
+ ```sh
35
+ insight-cli tools list --json
36
+ insight-cli tools show die --json
37
+ insight-cli skill insight-die --json
38
+ ```
39
+
40
+ The catalog describes the adapters and their packaged skills before any runtime is downloaded.
41
+ Use each tool's `status` to check the selected profile, then follow its skill and generated help.
42
+ The toolbox includes Ghidra, ILSpy, 7-Zip, LLVM utilities, DiE, LLDB, Frida, WinDbg, strace and .NET dump/stack/trace; platform
43
+ and capability limits are explicit per tool. A partial classification or a failed native process
44
+ is not a complete finding. Preserve useful output in ordinary project files and checkpoint it
45
+ with `artifacts save` when useful. Existing project RE instructions retain precedence.
46
+
24
47
  ## Start
25
48
 
26
49
  ```sh
@@ -59,3 +82,5 @@ License: MIT. The bundled GhidraMCP bridge has its own Apache-2.0 license and no
59
82
 
60
83
  Runtime management, local archives and external paths: [managed runtime](references/managed-runtime.md).
61
84
  The host debugger and OS permissions are checked separately by `ghidra doctor`.
85
+
86
+ Static .NET commands and ordinary output files: [ILSpy](references/ilspy.md).
package/SKILL.md CHANGED
@@ -1,58 +1,42 @@
1
1
  ---
2
2
  name: insight-cli
3
- description: Research several executable inputs through durable independent sessions and isolated Ghidra contexts using the matching insight-cli facade. Agents supply the investigation and interpret results.
3
+ description: Choose and prepare reverse-engineering capabilities from the insight-cli toolbox for binary, managed-code and runtime investigations. Use to discover the appropriate tool or its packaged skill before installing native runtimes.
4
4
  ---
5
5
 
6
- # insight-cli 0.2.0
7
-
8
- Use `ghidra status` to inspect runtime readiness; `ghidra install` delivers the pinned runtime.
9
- For archives, external launchers, server lifecycle or removal, read [managed runtime](references/managed-runtime.md).
10
-
11
- This skill and its executable helper are one npm package. Run `insight-cli skill` to locate
12
- these installed resources. Use generated `--help` for syntax; read the references as needed.
13
- Follow applicable project RE rules for tools, source of truth, evidence layout and format;
14
- this package's walkthroughs fill gaps rather than replacing those conventions.
15
-
16
- For coordinating a reverse-engineering investigation with ordinary files, external tools
17
- and multiple agents, read the packaged [Insight RE skill](skills/insight-re/SKILL.md),
18
- also located by `insight-cli skill insight-re`. When a retained checkpoint is useful, save
19
- a completed project file or folder with
20
- `insight-cli artifacts save <path>`; [save semantics](references/artifacts.md) describe the
21
- ordinary saved copy and its receipt. Neither operation requires a Ghidra installation.
22
-
23
- 1. Select the configured runtime profile. Ordinary work uses a managed local server; an external
24
- server is optional. See [setup](references/setup.md). Factory permissions authorize changes.
25
- 2. Open the input with `ghidra open <input> --session new`. Retain the returned session and target.
26
- Another agent chooses `new` independently; one session can open several inputs.
27
- 3. Pass both `--session` and `--target` on research calls. Follow strings to xrefs and their
28
- function addresses, then inspect/decompile. See [research](references/research.md).
29
- 4. Rename functions or set/clear comments through ordinary commands. An `applied` result means
30
- verified saved private work. Other sessions keep their own views; local edits remain unpublished in the default manual mode.
31
- 5. By default, publish explicitly with `ghidra merge`; receive safe shared changes with `ghidra refresh`.
32
- Resolve overlapping names/comments against an explicitly observed shared value. A conflict
33
- prevents the whole selected merge and retains local work.
34
- 6. Continue with `ghidra open --session <id> --target <id>`. For uncertain outcomes inspect
35
- `sessions status <id> --target <id>` and [recovery](references/recovery.md). Supplying a stable
36
- optional `--request-id` lets a repeated changing intent retrieve its outcome without rerunning.
37
-
38
- The facade exposes the pinned static research/editing catalog, merge/refresh, project/server/GUI
39
- controls, debugger, archive exchange and supported recovery. Preserve private work
40
- and journals while an outcome is unresolved. The CLI supplies the investigation tools; agents
41
- choose research goals and interpret findings.
42
- Installing this package does not register this skill in an agent's configuration.
43
-
44
- For project files, program export/import and configured-server administration, read
45
- [administration](references/administration.md). These operations preserve separate research views;
46
- their external effects do not participate in program merge.
47
-
48
- For owned GUI execution, CPU state, breakpoints and retained traces, read
49
- [debugger](references/debugger.md). Execution side effects remain separate from program publication.
50
-
51
- For explicit external documentation exchange and retained submission outcomes, read
52
- [archive](references/archive.md).
53
-
54
- For selected native SDK extensions (VT, DB differences, byte/assembly edits, formats, GDT,
55
- FID/BSim, namespaces and typed IR), read [native workflows](references/native-workflows.md).
56
-
57
- For managed SDK extension modules, actual language/analyzer/plugin discovery and opt-in
58
- automatic synchronization, read [extensions and sync](references/extensions-and-sync.md).
6
+ # insight-cli 0.2.1
7
+
8
+ If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
+ with the agent host's normal permission escalation, then use that route for later authorized
10
+ CLI calls too. An explicit **no command was sent** denial is known undispatched and can be
11
+ retried through that route. Keep HOME, profile and owner state; see
12
+ [host execution permissions](references/agent-execution.md). A lost mutation reply needs
13
+ request/status recovery, never blind retry.
14
+
15
+ Read the project's RE instructions and existing findings first. They own tool choices,
16
+ evidence layout, formats and source of truth. These skills fill the remaining gaps.
17
+
18
+ 1. Run `insight-cli tools list --json` to discover the capabilities shipped in this version.
19
+ The catalog works before profile configuration, downloads or IPC startup. A downloaded
20
+ runtime is not needed to discover what a tool does.
21
+ 2. Use `insight-cli tools show <tool> --json` for tasks, supported inputs/platforms,
22
+ dependencies and its skill path. Read that skill before preparing or using the tool.
23
+ 3. Select a profile for execution. Run the selected application's `status` and generated
24
+ `--help`. `install` prepares its private runtime; archives/offline and external paths
25
+ are tool-specific and described in its skill. Update permission is required for tool
26
+ preparation/execution and saved changes: `insight-cli permissions grant Update`.
27
+ 4. Answer the question with focused queries and ordinary project files. Follow results to
28
+ useful detail; a large raw dump is not an interpretation. External tools remain welcome.
29
+ 5. Preserve completed files with `insight-cli artifacts save <path> --json` when a retained
30
+ checkpoint helps. For several agents sharing Ghidra analysis, use separate sessions,
31
+ then explicit merge/refresh as described by its skill.
32
+
33
+ `insight-cli skill` locates this entry point. `skill insight-re` gives investigation and
34
+ multi-agent guidance; `skill insight-ghidra`, `skill insight-ilspy` and
35
+ `skill insight-artifacts` locate the relevant instructions. Skills ship with the CLI;
36
+ installing npm binaries does not register them in an agent host. See
37
+ [agent connection](references/agent-setup.md) for current setup and access requirements.
38
+
39
+ Use generated help as the syntax authority. Catalog metadata describes shipped capabilities;
40
+ profile runtime readiness comes from the selected tool's `status`. Unavailable profile/IPC
41
+ access means execution readiness is unknown. Preserve work and diagnose access before trying
42
+ again; stopping a shared owner does not grant a denied agent access to it.
@@ -0,0 +1,3 @@
1
+ import { type CommandContext, type CommandDefinition } from '@eyeauras/cli-factory';
2
+ import type { Workspace } from './workspace.js';
3
+ export declare function binaryCommands(workspace: (c: CommandContext) => Workspace): CommandDefinition[];
@@ -0,0 +1,74 @@
1
+ import { command, Permission, CliError } from '@eyeauras/cli-factory';
2
+ import { join, resolve, dirname } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { mkdir, writeFile, copyFile, readFile } from 'node:fs/promises';
5
+ import { constants } from 'node:fs';
6
+ import { release } from 'node:os';
7
+ import { randomUUID } from 'node:crypto';
8
+ import { runTool } from './tool-runtime/run.js';
9
+ import { atomicWrite } from './tool-runtime/store.js';
10
+ import { fileSha256 } from './tool-runtime/archives.js';
11
+ import { fail, text, id } from './model.js';
12
+ import { number } from './research.js';
13
+ const helper = fileURLToPath(new URL('../../runtime/native/binary/insight-binary-darwin-arm64', import.meta.url));
14
+ export function binaryCommands(workspace) {
15
+ const run = (mode) => command(mode + ' [input]', mode === 'query' ? 'Inspect bounded PE, ELF or thin Mach-O metadata without executing the input' : 'Change one expected PE subsystem field in a new copy and independently read it back', async ({ args, options: o }, c) => {
16
+ if (process.platform !== 'darwin' || process.arch !== 'arm64' || Number(release().split('.')[0]) < 23)
17
+ fail('unsupported', 'The packaged LIEF facade is currently verified on macOS14+ ARM64; input formats are PE, ELF and thin Mach-O.');
18
+ if (Boolean(args.input) === Boolean(o.target))
19
+ fail('invalid', 'Supply one binary input or --target.');
20
+ const view = mode === 'query' ? text(o.view ?? 'overview', 16) : undefined;
21
+ if (view && !['overview', 'sections', 'libraries', 'imports', 'exports'].includes(view))
22
+ fail('invalid', 'Use overview, sections, libraries, imports or exports.');
23
+ const limit = number(o.limit ?? 50, 500, 1), offset = number(o.offset ?? 0, 1000000), w = workspace(c), target = args.input ? await w.importTarget(resolve(c.cwd, text(args.input, 4096))) : w.target(id(o.target));
24
+ if (target.input.size > 64 * 1024 ** 2)
25
+ fail('limit', 'Structured binary input exceeds 64 MiB.');
26
+ const input = await w.artifacts.verify(target.input);
27
+ const directory = join(c.appArguments.AppDataDirectory, 'runtime/binary/queries', randomUUID()), plan = join(directory, 'plan.json'), edited = join(directory, 'edited.exe');
28
+ let edit;
29
+ if (mode === 'edit-subsystem') {
30
+ if (!o.output)
31
+ fail('invalid', 'Copy-only editing requires --output FILE.');
32
+ const values = { gui: 2, console: 3 }, expected = values[text(o.expectSubsystem, 16)], value = values[text(o.subsystem, 16)];
33
+ if (!expected || !value || expected === value)
34
+ fail('invalid', 'Choose a different gui/console subsystem and an explicit --expect-subsystem.');
35
+ edit = { expectedSubsystem: expected, subsystem: value, output: edited };
36
+ }
37
+ await atomicWrite(plan, { schema: 1, mode, input, view, filter: o.filter === undefined ? undefined : text(o.filter, 4096), limit, offset, ...edit });
38
+ const result = await runTool(c, { tool: 'binary', role: mode, executable: helper, arguments: [plan], timeoutMs: 60000, maxOutputBytes: 8 * 1024 ** 2, nativeDeadline: true, target: target.id, metadata: { view, helperSha256: await fileSha256(helper) } });
39
+ let observation;
40
+ try {
41
+ observation = JSON.parse(result.stdout);
42
+ }
43
+ catch {
44
+ throw new CliError('Binary parser did not return complete bounded JSON.', { code: 'tool.partial', result: { process: result.process, diagnostics: result.diagnostics } });
45
+ }
46
+ if (!['completed', 'partial'].includes(observation?.state) || typeof observation.complete !== 'boolean')
47
+ fail('partial', 'Binary query receipt was not verified.', { process: result.process, diagnostics: result.diagnostics });
48
+ if (await fileSha256(input) !== target.binarySha256)
49
+ fail('binding', 'Immutable binary changed during inspection.');
50
+ const warnings = result.stderr.trim(), value = { ...observation, ...(warnings ? { state: 'partial', complete: false, reason: 'native_parser_diagnostics', warnings: warnings.slice(0, 4096), warningsTruncated: warnings.length > 4096 } : {}), target: target.id, inputSha256: target.binarySha256, process: result.process, elapsedMs: result.elapsedMs, diagnostics: result.diagnostics };
51
+ if (mode === 'edit-subsystem') {
52
+ if (!value.complete)
53
+ fail('partial', 'Native parser diagnostics prevent accepting the copied edit.', value);
54
+ const before = await readFile(input), after = await readFile(edited), at = Number(BigInt(observation.fieldOffset));
55
+ if (after.length !== before.length || !Number.isSafeInteger(at) || at < 0 || at + 2 > before.length)
56
+ fail('binding', 'Copied PE edit did not retain its field bounds.');
57
+ for (let n = 0; n < before.length; n++)
58
+ if (n !== at && n !== at + 1 && before[n] !== after[n])
59
+ fail('binding', 'Copied PE edit changed bytes outside the declared field.');
60
+ const output = resolve(c.cwd, text(o.output, 4096));
61
+ await mkdir(dirname(output), { recursive: true, mode: 0o700 });
62
+ await copyFile(edited, output, constants.COPYFILE_EXCL);
63
+ return { ...value, output, outputSha256: await fileSha256(output), originalPreserved: true };
64
+ }
65
+ if (o.output) {
66
+ const output = resolve(c.cwd, text(o.output, 4096)), content = JSON.stringify(value, null, 2) + '\n';
67
+ await mkdir(dirname(output), { recursive: true, mode: 0o700 });
68
+ await writeFile(output, content, { flag: 'wx', mode: 0o600 });
69
+ return { state: value.state, complete: value.complete, reason: value.reason, target: target.id, output, bytes: Buffer.byteLength(content), process: result.process, diagnostics: result.diagnostics };
70
+ }
71
+ return value;
72
+ }, { permission: Permission.Update, options: [{ flags: '--target <id>', description: 'Reuse immutable input bytes' }, { flags: '--output <file>', description: mode === 'query' ? 'Save this bounded page to a new JSON file' : 'Required new executable copy; never overwrite an existing file' }, ...(mode === 'query' ? [{ flags: '--view <kind>', description: 'overview, sections, libraries, imports or exports', defaultValue: 'overview' }, { flags: '--filter <text>', description: 'Literal metadata name substring before pagination' }, { flags: '--limit <count>', description: 'Return 1–500 rows', defaultValue: 50 }, { flags: '--offset <count>', description: 'Skip matching rows', defaultValue: 0 }] : [{ flags: '--expect-subsystem <kind>', description: 'Required current PE subsystem: gui or console', required: true }, { flags: '--subsystem <kind>', description: 'Required different PE subsystem: gui or console', required: true }])] });
73
+ return [command('binary', 'Structured binary metadata and guarded copy-only edits', [run('query'), run('edit-subsystem')])];
74
+ }
@@ -0,0 +1,3 @@
1
+ import { type CommandContext, type CommandDefinition } from '@eyeauras/cli-factory';
2
+ import type { Workspace } from './workspace.js';
3
+ export declare function captureCommands(workspace: (c: CommandContext) => Workspace): CommandDefinition[];
@@ -0,0 +1,220 @@
1
+ import { command, Permission, CliError } from '@eyeauras/cli-factory';
2
+ import { join, resolve, dirname, basename, sep } from 'node:path';
3
+ import { mkdir, writeFile, copyFile, chmod, open, realpath, lstat } from 'node:fs/promises';
4
+ import { constants } from 'node:fs';
5
+ import { release } from 'node:os';
6
+ import { createHash } from 'node:crypto';
7
+ import { runTool } from './tool-runtime/run.js';
8
+ import { atomicWrite, readJson } from './tool-runtime/store.js';
9
+ import { listProcesses } from './tool-runtime/supervisor.js';
10
+ import { fileSha256 } from './tool-runtime/archives.js';
11
+ import { fail, text, id } from './model.js';
12
+ import { number } from './research.js';
13
+ const sha = (b) => createHash('sha256').update(b).digest('hex');
14
+ const list = (v) => v === undefined ? [] : (Array.isArray(v) ? v : [v]).map(s => text(s, 4096));
15
+ const root = (c, request) => { if (!/^a_[a-f0-9-]{36}$/.test(request))
16
+ fail('invalid', 'Select a capture request returned by capture run.'); return join(c.appArguments.AppDataDirectory, 'runtime/capture', request); };
17
+ function relativeFile(value) { const name = text(value, 1024); if (name.includes('\\') || name.startsWith('/') || name.split('/').some(p => !p || p === '.' || p === '..') || name.toLowerCase() === 'subject')
18
+ fail('invalid', 'Watch paths must be ordinary relative files inside the owned working directory.'); return name; }
19
+ async function boundedFile(path, max = 16 * 1024 ** 2) {
20
+ const handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);
21
+ try {
22
+ const before = await handle.stat();
23
+ if (!before.isFile() || before.size > max)
24
+ fail('limit', 'Selected file must be regular and within its byte bound.');
25
+ const chunks = [];
26
+ let bytes = 0;
27
+ for await (const chunk of handle.createReadStream({ autoClose: false })) {
28
+ bytes += chunk.length;
29
+ if (bytes > max)
30
+ fail('limit', 'Selected file grew beyond its capture bound.');
31
+ chunks.push(chunk);
32
+ }
33
+ const after = await handle.stat();
34
+ if (before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || before.ino !== after.ino)
35
+ fail('binding', 'Selected file changed while being read.');
36
+ return Buffer.concat(chunks);
37
+ }
38
+ finally {
39
+ await handle.close();
40
+ }
41
+ }
42
+ async function snapshot(directory, name) {
43
+ const file = join(directory, name);
44
+ try {
45
+ const parent = await realpath(dirname(file)), base = await realpath(directory);
46
+ if (parent !== base && !parent.startsWith(base + sep))
47
+ return { path: name, state: 'unavailable', reason: 'parent_outside_owned_directory' };
48
+ const info = await lstat(file);
49
+ if (!info.isFile() || info.isSymbolicLink())
50
+ return { path: name, state: 'unavailable', reason: 'not_regular_file' };
51
+ const bytes = await boundedFile(file);
52
+ return { path: name, state: 'present', bytes: bytes.length, sha256: sha(bytes) };
53
+ }
54
+ catch (error) {
55
+ if (error.code === 'ENOENT')
56
+ return { path: name, state: 'absent' };
57
+ return { path: name, state: 'unavailable', reason: error.code ?? 'unreadable' };
58
+ }
59
+ }
60
+ function pageStream(value, offset, limit) { if (!value)
61
+ return { available: false }; const all = Buffer.from(value.base64, 'base64'), bytes = all.subarray(offset, offset + limit); return { available: true, totalBytes: value.bytes, sha256: value.sha256, offset, limit, base64: bytes.toString('base64'), text: bytes.toString('utf8'), textEncoding: 'UTF-8 preview with replacement; base64 preserves exact selected bytes', truncated: offset + limit < all.length }; }
62
+ function overview(receipt) { const { stdout, stderr, files, ...rest } = receipt; return { ...rest, stdout: pageStream(stdout, 0, 256), stderr: pageStream(stderr, 0, 256), declaredFiles: files.length, fileChanges: files.filter(f => f.change !== 'unchanged').map(f => ({ path: f.path, change: f.change })) }; }
63
+ async function exportReceipt(c, value, option) { const output = resolve(c.cwd, text(option, 4096)), content = JSON.stringify(value, null, 2) + '\n'; await mkdir(dirname(output), { recursive: true, mode: 0o700 }); await writeFile(output, content, { flag: 'wx', mode: 0o600 }); return output; }
64
+ async function receiptFor(c, w, request) { const stored = w.administration(request); if (stored.operation !== 'capture.run')
65
+ fail('invalid', 'Request is not an owned process capture.'); const file = join(root(c, request), 'capture.json'), receipt = await readJson(file); if (receipt && stored.state === 'applied') {
66
+ const result = stored.result;
67
+ if (result?.receiptSha256 !== await fileSha256(file))
68
+ fail('binding', 'Capture receipt differs from its durable outcome.');
69
+ validateReport(receipt);
70
+ if (receipt.request !== request)
71
+ fail('binding', 'Capture receipt has a different request identity.');
72
+ return receipt;
73
+ } return { state: stored.state === 'accepted' ? 'prepared' : 'unknown', complete: false, request, intent: stored.intent, processes: (await listProcesses(c.appArguments.AppDataDirectory, { tool: 'capture' })).filter(p => p.metadata?.request === request), directory: root(c, request), workingDirectory: join(root(c, request), 'working'), scope: 'No completed capture receipt. Inspect retained process/input/files explicitly; never rerun this request to manufacture a result.' }; }
74
+ function validateReport(value) {
75
+ const hash = (v) => typeof v === 'string' && /^[a-f0-9]{64}$/.test(v);
76
+ if (value?.schema !== 1 || value.kind !== 'insight-process-capture' || typeof value.complete !== 'boolean' || value.state !== (value.complete ? 'completed' : 'partial') || !hash(value.inputSha256) || !Array.isArray(value.files) || value.files.length > 32 || !value.execution || !Array.isArray(value.arguments) || value.arguments.length > 64 || value.arguments.some(a => typeof a !== 'string' || a.length > 4096) || !Array.isArray(value.inputs) || value.inputs.length > 32)
77
+ fail('invalid', 'Select a structured insight process capture report.');
78
+ if (value.execution.exitCode !== null && (!Number.isInteger(value.execution.exitCode) || value.execution.exitCode < 0 || value.execution.exitCode > 255))
79
+ fail('invalid', 'Invalid captured exit code.');
80
+ let bytes = 0;
81
+ for (const stream of [value.stdout, value.stderr])
82
+ if (stream) {
83
+ if (!hash(stream.sha256) || typeof stream.base64 !== 'string')
84
+ fail('invalid', 'Malformed capture byte stream.');
85
+ const raw = Buffer.from(stream.base64, 'base64');
86
+ if (raw.toString('base64') !== stream.base64 || raw.length !== stream.bytes || sha(raw) !== stream.sha256 || (bytes += raw.length) > 4 * 1024 ** 2)
87
+ fail('binding', 'Capture byte stream differs from its bounds/hash.');
88
+ }
89
+ if (value.complete && (!value.stdout || !value.stderr || value.execution.exitCode === null || value.execution.signal !== null))
90
+ fail('invalid', 'A complete capture requires known terminal output and exit.');
91
+ const seen = new Set();
92
+ for (const file of value.files) {
93
+ const name = relativeFile(file.path);
94
+ if (seen.has(name))
95
+ fail('invalid', 'Duplicate declared capture path.');
96
+ seen.add(name);
97
+ for (const observed of [file.before, file.after])
98
+ if (!observed || observed.path !== name || !['present', 'absent', 'unavailable'].includes(observed.state) || observed.state === 'present' && (!hash(observed.sha256) || !Number.isSafeInteger(observed.bytes) || observed.bytes < 0 || observed.bytes > 16 * 1024 ** 2))
99
+ fail('invalid', 'Malformed declared file observation.');
100
+ }
101
+ }
102
+ export function captureCommands(workspace) {
103
+ const run = command('run [input]', 'Capture one explicitly selected owned native execution and declared file snapshots', async ({ args, options: o }, c) => {
104
+ if (process.platform !== 'darwin' || process.arch !== 'arm64' || Number(release().split('.')[0]) < 23)
105
+ fail('unsupported', 'Process capture is verified on macOS14+ ARM64 thin native executables.');
106
+ if (Boolean(args.input) === Boolean(o.target))
107
+ fail('invalid', 'Supply one native program or --target.');
108
+ const w = workspace(c), target = args.input ? await w.importTarget(resolve(c.cwd, text(args.input, 4096))) : w.target(id(o.target)), input = await w.artifacts.verify(target.input);
109
+ if (target.input.size > 64 * 1024 ** 2)
110
+ fail('limit', 'Owned executable exceeds 64 MiB.');
111
+ const header = (await boundedFile(input, 64 * 1024 ** 2)).subarray(0, 32);
112
+ if (header.length < 32 || header.subarray(0, 4).toString('hex') !== 'cffaedfe' || header.readUInt32LE(4) !== 0x0100000c || header.readUInt32LE(12) !== 2)
113
+ fail('unsupported', 'Select a thin ARM64 Mach-O executable, not a PE/ELF, script, library or universal container.');
114
+ const argv = list(o.arg), selected = list(o.inputFile), watched = [...new Set(list(o.watch).map(relativeFile))];
115
+ if (argv.length > 64 || selected.length > 32 || watched.length > 32)
116
+ fail('limit', 'Capture permits 64 literal arguments, 32 selected input files and 32 watch paths.');
117
+ const timeoutMs = number(o.timeoutSeconds ?? 10, 600, 1) * 1000, files = [];
118
+ let total = 0;
119
+ for (const option of selected) {
120
+ const path = resolve(c.cwd, option), name = basename(path);
121
+ if (name.toLowerCase() === 'subject' || files.some(f => f.name.normalize('NFD').toLowerCase() === name.normalize('NFD').toLowerCase()) || !/^[^/\\\0]+$/.test(name))
122
+ fail('invalid', 'Selected input basenames must be ordinary and unique.');
123
+ const data = await boundedFile(path);
124
+ if ((total += data.length) > 64 * 1024 ** 2)
125
+ fail('limit', 'Selected input files exceed 64 MiB.');
126
+ files.push({ name, sha256: sha(data), bytes: data.length, data });
127
+ }
128
+ const stdin = o.stdinFile ? await boundedFile(resolve(c.cwd, text(o.stdinFile, 4096)), 1024 ** 2) : Buffer.alloc(0);
129
+ if (o.output && !(o.requestId && w.administrationByCaller(id(o.requestId))))
130
+ try {
131
+ await lstat(resolve(c.cwd, text(o.output, 4096)));
132
+ fail('invalid', 'Capture output already exists.');
133
+ }
134
+ catch (error) {
135
+ if (error.code !== 'ENOENT')
136
+ throw error;
137
+ }
138
+ const intent = { target: target.id, inputSha256: target.binarySha256, arguments: argv, inputs: files.map(({ data, ...f }) => f), stdin: { sha256: sha(stdin), bytes: stdin.length }, watch: watched, timeoutMs, output: o.output ? resolve(c.cwd, text(o.output, 4096)) : undefined };
139
+ const reservation = w.reserveAdministration('capture.run', intent, o.requestId === undefined ? undefined : id(o.requestId)), request = reservation.request.id;
140
+ if (reservation.replay) {
141
+ const previous = await receiptFor(c, w, request);
142
+ if (reservation.request.state === 'applied' && 'kind' in previous) {
143
+ if (!previous.complete)
144
+ throw new CliError('Prior capture remains partial; no execution was repeated.', { code: 'tool.capture.partial', result: overview(previous) });
145
+ return { ...overview(previous), replayed: true };
146
+ }
147
+ throw new CliError('Capture request already exists without a verified complete outcome; no execution was repeated.', { code: 'tool.capture.unknown', result: previous });
148
+ }
149
+ const directory = root(c, request), working = join(directory, 'working'), subject = join(working, 'subject');
150
+ await mkdir(working, { recursive: true, mode: 0o700 });
151
+ await copyFile(input, subject, constants.COPYFILE_EXCL);
152
+ await chmod(subject, 0o700);
153
+ if (await fileSha256(subject) !== target.binarySha256)
154
+ fail('binding', 'Owned executable differs from captured input.');
155
+ for (const f of files)
156
+ await writeFile(join(working, f.name), f.data, { flag: 'wx', mode: 0o600 });
157
+ const before = await Promise.all(watched.map(name => snapshot(working, name)));
158
+ await atomicWrite(join(directory, 'intent.json'), { request, ...intent });
159
+ w.administrationState(request, 'running', { directory });
160
+ let result, failure;
161
+ try {
162
+ result = await runTool(c, { tool: 'capture', role: 'run', executable: subject, arguments: argv, cwd: working, input: stdin, timeoutMs, maxOutputBytes: 4 * 1024 ** 2, retainRawOutput: true, nativeDeadline: true, acceptedCodes: Array.from({ length: 127 }, (_, n) => n), target: target.id, metadata: { request, working, scope: 'Owned program copy; selected input copies and declared file snapshots; no shell or OS sandbox' } });
163
+ }
164
+ catch (error) {
165
+ failure = error;
166
+ if (error instanceof CliError && error.result && typeof error.result === 'object' && 'stdout' in error.result)
167
+ result = error.result;
168
+ }
169
+ const after = await Promise.all(watched.map(name => snapshot(working, name))), unavailable = [...before, ...after].some(f => f.state === 'unavailable');
170
+ const stream = async (file) => { if (!file)
171
+ return; const b = await boundedFile(file, 4 * 1024 ** 2); return { bytes: b.length, sha256: sha(b), base64: b.toString('base64') }; };
172
+ const value = { schema: 1, kind: 'insight-process-capture', request, state: failure || unavailable ? 'partial' : 'completed', complete: !failure && !unavailable, ...(failure ? { reason: failure instanceof CliError ? failure.code : 'capture_failed' } : unavailable ? { reason: 'declared_file_unavailable' } : {}), target: target.id, inputSha256: target.binarySha256, timeoutMs, arguments: argv, inputs: intent.inputs, stdin: intent.stdin, stdout: await stream(result?.rawStdout), stderr: await stream(result?.rawStderr), execution: { process: result?.process, exitCode: result?.exitCode ?? null, signal: result?.signal ?? null, elapsedMs: result?.elapsedMs, diagnostics: result?.diagnostics }, files: watched.map((path, n) => { const a = before[n], b = after[n]; return { path, before: a, after: b, change: a.state === 'unavailable' || b.state === 'unavailable' ? 'unknown' : a.state === b.state && (a.state === 'absent' || a.sha256 === b.sha256) ? 'unchanged' : a.state === 'absent' ? 'created' : b.state === 'absent' ? 'deleted' : 'changed' }; }), scope: 'One owned program copy with literal argv, exact bounded stdout/stderr bytes and selected file snapshots. This is not an OS sandbox, a trace of all filesystem/network effects or proof of causality. Native deadline assumes the subject does not deliberately replace the inherited alarm. Known nonzero subject exits are captured outcomes; interrupted/overflow/unknown capture stays partial.' };
173
+ if (!value.stdout || !value.stderr) {
174
+ value.complete = false;
175
+ value.state = 'partial';
176
+ value.reason ??= 'raw_output_unavailable';
177
+ }
178
+ const path = join(directory, 'capture.json');
179
+ await atomicWrite(path, value);
180
+ w.administrationState(request, 'applied', { receipt: path, receiptSha256: await fileSha256(path), complete: value.complete });
181
+ const output = o.output ? await exportReceipt(c, value, o.output) : undefined;
182
+ if (!value.complete)
183
+ throw new CliError('Capture is partial; retained output/files are available and execution was not replayed.', { code: 'tool.capture.partial', result: { ...overview(value), directory, ...(output ? { output } : {}) } });
184
+ return { ...overview(value), directory, ...(output ? { output } : {}) };
185
+ }, { permission: Permission.Update, options: [{ flags: '--target <id>', description: 'Reuse immutable native program bytes' }, { flags: '--arg <text...>', description: 'Literal subject arguments; no shell string or expansion' }, { flags: '--input-file <file...>', description: 'Copy selected regular files by unique basename into owned cwd' }, { flags: '--stdin-file <file>', description: 'Optional bounded input byte stream (up to 1 MiB)' }, { flags: '--watch <path...>', description: 'Declared relative regular files to snapshot before and after execution' }, { flags: '--timeout-seconds <seconds>', description: 'Owned execution deadline (1–600)', defaultValue: 10 }, { flags: '--output <file>', description: 'Save a new portable bounded JSON capture, including exact output base64' }, { flags: '--request-id <id>', description: 'Retrieve this exact capture intent without executing it again' }] });
186
+ const show = command('show <request>', 'Inspect retained capture bytes or an unresolved intent without rerunning a program', async ({ args, options: o }, c) => { const request = text(args.request, 128), value = await receiptFor(c, workspace(c), request); if (!('kind' in value))
187
+ return value; if (o.output)
188
+ return { request, complete: value.complete, output: await exportReceipt(c, value, o.output) }; const view = text(o.view ?? 'overview', 16), limit = number(o.limit ?? 50, 1000, 1), offset = number(o.offset ?? 0, 8 * 1024 ** 2); if (view === 'overview')
189
+ return overview(value); if (view === 'stdout' || view === 'stderr')
190
+ return { request, state: value.state, complete: value.complete, view, ...pageStream(value[view], offset, limit) }; if (view === 'files')
191
+ return { request, state: value.state, complete: value.complete, items: value.files.slice(offset, offset + limit), total: value.files.length, offset, limit, truncated: offset + limit < value.files.length }; fail('invalid', 'Use overview, stdout, stderr or files.'); }, { permission: Permission.Update, options: [{ flags: '--view <kind>', description: 'overview, stdout, stderr or files', defaultValue: 'overview' }, { flags: '--limit <count>', description: '1–1000 output bytes or file rows', defaultValue: 50 }, { flags: '--offset <count>', description: 'Skip output bytes or file rows', defaultValue: 0 }, { flags: '--output <file>', description: 'Export portable retained capture to a new ordinary JSON file' }] });
192
+ const compare = command('compare <left> <right>', 'Compare two retained capture reports without re-executing their subjects', async ({ args, options: o }, c) => {
193
+ async function load(path) { const file = resolve(c.cwd, text(path, 4096)), bytes = await boundedFile(file, 8 * 1024 ** 2); let value; try {
194
+ value = JSON.parse(bytes.toString('utf8'));
195
+ }
196
+ catch {
197
+ fail('invalid', 'Capture report must be bounded JSON.');
198
+ } validateReport(value); return { value, sha256: sha(bytes) }; }
199
+ const left = await load(args.left), right = await load(args.right), a = left.value, b = right.value, changes = [], unknown = [];
200
+ for (const field of ['stdout', 'stderr']) {
201
+ if (!a[field] || !b[field])
202
+ unknown.push(field);
203
+ else if (a[field].sha256 !== b[field].sha256)
204
+ changes.push({ field, left: a[field].sha256, right: b[field].sha256 });
205
+ }
206
+ if (a.execution.exitCode !== b.execution.exitCode || a.execution.signal !== b.execution.signal)
207
+ changes.push({ field: 'exit', left: a.execution, right: b.execution });
208
+ const af = new Map(a.files.map(f => [f.path, f])), bf = new Map(b.files.map(f => [f.path, f]));
209
+ for (const name of [...new Set([...af.keys(), ...bf.keys()])].sort()) {
210
+ const l = af.get(name)?.after, r = bf.get(name)?.after;
211
+ if (!l || !r || l.state === 'unavailable' || r.state === 'unavailable')
212
+ unknown.push('file:' + name);
213
+ else if (l.state !== r.state || l.sha256 !== r.sha256)
214
+ changes.push({ field: 'file:' + name, left: l, right: r });
215
+ }
216
+ const limit = number(o.limit ?? 50, 500, 1), offset = number(o.offset ?? 0, 1000000), complete = a.complete && b.complete && !unknown.length;
217
+ return { state: complete ? 'completed' : 'partial', complete, left: { reportSha256: left.sha256, inputSha256: a.inputSha256 }, right: { reportSha256: right.sha256, inputSha256: b.inputSha256 }, sameDeclaredIntent: JSON.stringify({ target: a.inputSha256, argv: a.arguments, inputs: a.inputs, stdin: a.stdin, watch: a.files.map(f => f.path), timeoutMs: a.timeoutMs }) === JSON.stringify({ target: b.inputSha256, argv: b.arguments, inputs: b.inputs, stdin: b.stdin, watch: b.files.map(f => f.path), timeoutMs: b.timeoutMs }), items: changes.slice(offset, offset + limit), total: changes.length, unknown, offset, limit, truncated: offset + limit < changes.length, scope: 'Literal retained field/byte comparison; no subject rerun, causal equivalence or execution-time speedup claim. Partial reports cannot prove global equality.' };
218
+ }, { permission: Permission.ReadOnly, options: [{ flags: '--limit <count>', description: 'Return 1–500 changed fields', defaultValue: 50 }, { flags: '--offset <count>', description: 'Skip changed fields', defaultValue: 0 }] });
219
+ return [command('capture', 'Own bounded native executions and compare explicitly retained observations', [run, show, compare])];
220
+ }
package/dist/src/cli.js CHANGED
@@ -1,8 +1,27 @@
1
+ import { captureCommands } from './capture.js';
2
+ import { binaryCommands } from './binary.js';
3
+ import { skillCommand, toolboxCommands } from './toolbox.js';
4
+ import { listProcesses } from './tool-runtime/supervisor.js';
5
+ import { diagnosticsCommands } from './dotnet-diagnostics.js';
6
+ import { fridaCommands } from './frida.js';
7
+ import { mitmproxyCommands } from './mitmproxy.js';
8
+ import { tsharkCommands } from './tshark.js';
9
+ import { dnspyCommands } from './dnspy.js';
10
+ import { procmonCommands } from './procmon.js';
11
+ import { straceCommands } from './strace.js';
12
+ import { windbgCommands } from './windbg.js';
13
+ import { lldbCommands } from './lldb.js';
14
+ import { dieCommands } from './die.js';
15
+ import { llvmCommands } from './llvm.js';
16
+ import { sevenzipCommands } from './sevenzip.js';
17
+ import { ilspyCommands } from './ilspy.js';
18
+ import { toolProcessCommands } from './tool-runtime/commands.js';
19
+ import { ghidraProcessHooks } from './ghidra-processes.js';
20
+ import { withToolLock, toolProfileBusy } from './tool-runtime/store.js';
1
21
  import { command, createCli, Permission, CliError, ProfileStore } from '@eyeauras/cli-factory';
2
22
  import { join, resolve } from 'node:path';
3
23
  import { readFile, readdir } from 'node:fs/promises';
4
24
  import { existsSync } from 'node:fs';
5
- import { fileURLToPath } from 'node:url';
6
25
  import { Workspace } from './workspace.js';
7
26
  import { GhidraContexts } from './contexts.js';
8
27
  import { nativeInputs } from './native-inputs.js';
@@ -28,6 +47,7 @@ import { Extensions, extensionCommands, extensionState, extensionInventoryComman
28
47
  import { Synchronization, synchronizationCommands } from './sync-policy.js';
29
48
  import { artifactsCommands } from './saved-materials.js';
30
49
  import { RuntimeManager, runtimeCommands, runtimeProcesses } from './runtime-manager.js';
50
+ import { packageVersion } from './package-version.js';
31
51
  import { runtimeSelection } from './runtime-selection.js';
32
52
  const bindingFields = ['java', 'ghidraHome', 'mcpJar', 'mcpJarSha256', 'server', 'repository', 'readerUser', 'publisherUser', 'maxContexts', 'debuggerPython', 'windbgDir', 'archiveUrl'];
33
53
  class Owner {
@@ -53,7 +73,7 @@ class Owner {
53
73
  current.workspace.close();
54
74
  this.profiles.delete(directory);
55
75
  }
56
- return await action();
76
+ return await withToolLock(directory, 'ghidra', action, c.signal);
57
77
  }
58
78
  finally {
59
79
  this.runtimeChanging.delete(directory);
@@ -78,7 +98,7 @@ class Owner {
78
98
  const backend = async () => {
79
99
  if (!selected.backend)
80
100
  selected.backend = Promise.resolve(this.options.backend ?
81
- this.options.backend(selected.workspace, c) : nativeInputs(c.profile.values, selected.workspace.directory).then(inputs => new GhidraContexts(selected.workspace, inputs, c)))
101
+ this.options.backend(selected.workspace, c) : nativeInputs(c.profile.values, selected.workspace.directory, c).then(inputs => new GhidraContexts(selected.workspace, inputs, c)))
82
102
  .catch(error => { selected.backend = undefined; throw error; });
83
103
  const result = await selected.backend;
84
104
  if (result instanceof GhidraContexts)
@@ -96,6 +116,10 @@ class Owner {
96
116
  const directory = app.AppDataDirectory, profile = this.profiles.get(directory);
97
117
  if (this.runtimeChanging.has(directory))
98
118
  fail('busy', 'Runtime preparation is in progress; finish it before changing or deleting the profile.');
119
+ if (toolProfileBusy(directory))
120
+ fail('busy', 'A tool operation is active.');
121
+ if ((await listProcesses(directory)).some(r => !['exited', 'failed'].includes(r.state)))
122
+ fail('busy', 'The profile has active or unverified tool processes.');
99
123
  const materials = await readdir(join(directory, 'materials')).catch(error => { if (error.code === 'ENOENT')
100
124
  return []; throw error; });
101
125
  if (existsSync(join(directory, 'workspace', 'workspace.sqlite')) || materials.length)
@@ -198,6 +222,17 @@ function scopedFailures(entry, owner, parents = []) {
198
222
  if (!selected)
199
223
  return await run(input, c);
200
224
  const services = owner.selected(c);
225
+ // First open of an already known target reserves its context inside Research.open.
226
+ // Existing contexts still use the command boundary to order automatic sync phases.
227
+ if (path[1] === 'open')
228
+ try {
229
+ services.workspace.context(selected);
230
+ }
231
+ catch (error) {
232
+ if (error instanceof CliError && error.code === 'coordinator.notFound')
233
+ return await run(input, c);
234
+ throw error;
235
+ }
201
236
  return await services.research.boundary(selected, async () => {
202
237
  const excluded = ['open', 'merge', 'refresh', 'sync-policy', 'close', 'changes', 'debugger', 'ui', 'version-tracking', 'archive', 'projects', 'repository', 'server', 'formats', 'libraries', 'plugins'];
203
238
  const eligible = entry.permission !== Permission.ReadOnly && entry.permission !== undefined && !excluded.includes(path[1]) && !['ghidra types archive-export', 'ghidra documentation transfer'].includes(name);
@@ -222,7 +257,7 @@ function scopedFailures(entry, owner, parents = []) {
222
257
  export function createDefinition(options = {}) {
223
258
  const owner = new Owner(options);
224
259
  const definition = {
225
- name: 'insight-cli', applicationId: 'insight-cli', version: '0.2.0', description: 'Isolated research contexts and coordinated Ghidra analysis',
260
+ name: 'insight-cli', applicationId: 'insight-cli', version: packageVersion, description: 'Isolated research contexts and coordinated Ghidra analysis',
226
261
  resources: [owner], permissions: { categories: [{ name: 'Destructive', description: 'Explicit deletion or replacement of retained research data', enabledByDefault: false }] }, ...(options.runtime ? { runtime: options.runtime } : {}),
227
262
  profile: { fields: fields.map(([name, flags, description]) => ({ name: name, flags: flags, description: description,
228
263
  ...(name === 'maxContexts' ? { normalize: (value) => number(value, 16, 1) } : {}) })) },
@@ -277,15 +312,25 @@ export function createDefinition(options = {}) {
277
312
  await c.secrets.delete('publisherPassword');
278
313
  },
279
314
  },
280
- builtins: [command('skill [name]', 'Locate the installed insight-cli or insight-re skill', ({ args }) => {
281
- const name = args.name === undefined ? 'insight-cli' : text(args.name);
282
- if (!['insight-cli', 'insight-re'].includes(name))
283
- fail('notFound', 'Unknown skill; choose insight-cli or insight-re.');
284
- return { version: '0.2.0', name, path: fileURLToPath(new URL(name === 'insight-re' ? '../../skills/insight-re/SKILL.md' : '../../SKILL.md', import.meta.url)),
285
- skills: ['insight-cli', 'insight-re'] };
286
- })],
315
+ builtins: [skillCommand()],
287
316
  commands: [
288
317
  ...artifactsCommands(),
318
+ ...diagnosticsCommands(c => owner.selected(c).workspace),
319
+ ...llvmCommands(c => owner.selected(c).workspace),
320
+ ...dieCommands(c => owner.selected(c).workspace),
321
+ ...lldbCommands(c => owner.selected(c).workspace),
322
+ ...windbgCommands(c => owner.selected(c).workspace),
323
+ ...procmonCommands(),
324
+ ...dnspyCommands(c => owner.selected(c).workspace),
325
+ ...tsharkCommands(c => owner.selected(c).workspace),
326
+ ...mitmproxyCommands(c => owner.selected(c).workspace),
327
+ ...straceCommands(c => owner.selected(c).workspace),
328
+ ...fridaCommands(c => owner.selected(c).workspace),
329
+ ...sevenzipCommands(c => owner.selected(c).workspace),
330
+ ...ilspyCommands(c => owner.selected(c).workspace),
331
+ ...binaryCommands(c => owner.selected(c).workspace),
332
+ ...captureCommands(c => owner.selected(c).workspace),
333
+ ...toolProcessCommands({ ghidra: ghidraProcessHooks(c => owner.selected(c).workspace, (scope, c) => owner.selected(c).lifecycle.change(scope, 'close')) }, toolboxCommands()),
289
334
  command('targets', 'Inspect immutable inputs', [
290
335
  command('add <input>', 'Consume input without starting a tool', async ({ args }, c) => targetView(await owner.selected(c).workspace.importTarget(resolve(c.cwd, text(args.input, 4096)))), { permission: Permission.Update }),
291
336
  command('list', 'List known inputs', ({ options: o }, c) => {
@@ -392,7 +437,7 @@ export function createDefinition(options = {}) {
392
437
  }, { permission: Permission.Update, options: [...scoped, at, { flags: '--prototype <signature>', description: 'Complete C prototype', required: true },
393
438
  { flags: '--calling-convention <name>', description: 'Explicit convention supported by the selected compiler specification' }, request] }),
394
439
  command('get', 'Read a function and entry comments', ({ options: o }, c) => owner.selected(c).research.function(scope(o), address(o.address)), { permission: Permission.ReadOnly, options: [...scoped, at] }),
395
- command('decompile', 'Read decompiled function text', ({ options: o }, c) => owner.selected(c).research.function(scope(o), address(o.address), true), { permission: Permission.ReadOnly, options: [...scoped, at] }),
440
+ command('decompile', 'Read a bounded Unicode window of one decompiled function', ({ options: o }, c) => owner.selected(c).research.function(scope(o), address(o.address), true, { limit: number(o.limitChars ?? 16000, 32768, 1), offset: number(o.offsetChars ?? 0, 4 * 1024 ** 2) }), { permission: Permission.ReadOnly, options: [...scoped, at, { flags: '--limit-chars <count>', description: 'Return 1–32768 Unicode characters', defaultValue: 16000 }, { flags: '--offset-chars <count>', description: 'Skip Unicode characters in the returned native text', defaultValue: 0 }] }),
396
441
  command('rename', 'Record a saved private name', ({ options: o }, c) => {
397
442
  const name = text(o.name, 512);
398
443
  if (name !== name.trim())