@eyeauras/insight-cli 0.3.2 → 0.4.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 (141) hide show
  1. package/.cli-package-build.json +1 -1
  2. package/README.md +34 -62
  3. package/SKILL.md +4 -1
  4. package/dist/src/arguments.js +9 -4
  5. package/dist/src/cli.js +45 -37
  6. package/dist/src/code-references.d.ts +48 -0
  7. package/dist/src/code-references.js +154 -0
  8. package/dist/src/context-diagnostics.d.ts +25 -0
  9. package/dist/src/context-diagnostics.js +82 -0
  10. package/dist/src/contexts.d.ts +13 -1
  11. package/dist/src/contexts.js +38 -9
  12. package/dist/src/function-boundaries.d.ts +9 -0
  13. package/dist/src/function-boundaries.js +68 -0
  14. package/dist/src/function-entries.d.ts +33 -0
  15. package/dist/src/function-entries.js +84 -0
  16. package/dist/src/function-inspection.d.ts +4 -2
  17. package/dist/src/function-inspection.js +94 -59
  18. package/dist/src/function-results.d.ts +3 -1
  19. package/dist/src/function-results.js +9 -3
  20. package/dist/src/inline-script.d.ts +15 -0
  21. package/dist/src/inline-script.js +62 -0
  22. package/dist/src/internal-timing.d.ts +3 -0
  23. package/dist/src/internal-timing.js +52 -0
  24. package/dist/src/lifecycle.js +14 -4
  25. package/dist/src/native-inputs.d.ts +1 -1
  26. package/dist/src/native-inputs.js +1 -1
  27. package/dist/src/native-queries.js +1 -1
  28. package/dist/src/persistent-client.d.ts +30 -0
  29. package/dist/src/persistent-client.js +125 -0
  30. package/dist/src/queries.js +4 -1
  31. package/dist/src/query-policy.js +9 -1
  32. package/dist/src/research-view.d.ts +6 -0
  33. package/dist/src/research-view.js +9 -0
  34. package/dist/src/research.d.ts +38 -0
  35. package/dist/src/research.js +78 -8
  36. package/dist/src/string-anchors.d.ts +43 -0
  37. package/dist/src/string-anchors.js +176 -0
  38. package/dist/src/sync-policy.js +3 -0
  39. package/dist/src/timed-backend.d.ts +3 -0
  40. package/dist/src/timed-backend.js +16 -0
  41. package/dist/src/transport.d.ts +1 -0
  42. package/dist/src/transport.js +4 -0
  43. package/dist/src/workspace.js +5 -2
  44. package/package.json +12 -1
  45. package/references/native/InsightAnchorScan.java +135 -0
  46. package/references/native/InsightCodeReferences.java +129 -0
  47. package/references/native/InsightFunctionBoundaries.java +56 -0
  48. package/references/native/InsightInlineExecutor.java +143 -0
  49. package/references/native/InsightInlineScript.java +14 -0
  50. package/references/native/InsightPeRanges.java +92 -0
  51. package/references/native/InsightResearchQueries.java +22 -1
  52. package/references/native/InsightResearchView.java +69 -0
  53. package/references/native/InsightStringAnchors.java +49 -0
  54. package/references/persistent-client.mjs +125 -0
  55. package/references/persistent.md +50 -0
  56. package/references/query-semantics.md +12 -0
  57. package/references/recovery.md +36 -0
  58. package/references/research.md +87 -0
  59. package/references/setup.md +1 -1
  60. package/references/sparse-navigation.md +173 -0
  61. package/runtime/GhidraMCP-7.0.0.jar +0 -0
  62. package/runtime/GhidraMCP-NOTICE +5 -0
  63. package/runtime/provenance.json +17 -3
  64. package/runtime/research-view.provenance.json +28 -0
  65. package/runtime/toolbox.json +10 -3
  66. package/skill-bundle/insight-artifacts/SKILL.md +1 -1
  67. package/skill-bundle/insight-artifacts/references/recovery.md +36 -0
  68. package/skill-bundle/insight-binary/SKILL.md +1 -1
  69. package/skill-bundle/insight-capture/SKILL.md +1 -1
  70. package/skill-bundle/insight-cli/SKILL.md +4 -1
  71. package/skill-bundle/insight-cli/references/persistent-client.mjs +125 -0
  72. package/skill-bundle/insight-cli/references/persistent.md +50 -0
  73. package/skill-bundle/insight-cli/references/recovery.md +36 -0
  74. package/skill-bundle/insight-cli/references/setup.md +1 -1
  75. package/skill-bundle/insight-die/SKILL.md +1 -1
  76. package/skill-bundle/insight-dnspy/SKILL.md +1 -1
  77. package/skill-bundle/insight-dotnet-dump/SKILL.md +1 -1
  78. package/skill-bundle/insight-dotnet-stack/SKILL.md +1 -1
  79. package/skill-bundle/insight-dotnet-trace/SKILL.md +1 -1
  80. package/skill-bundle/insight-frida/SKILL.md +1 -1
  81. package/skill-bundle/insight-ghidra/SKILL.md +14 -1
  82. package/skill-bundle/insight-ghidra/references/persistent-client.mjs +125 -0
  83. package/skill-bundle/insight-ghidra/references/persistent.md +50 -0
  84. package/skill-bundle/insight-ghidra/references/query-semantics.md +12 -0
  85. package/skill-bundle/insight-ghidra/references/recovery.md +36 -0
  86. package/skill-bundle/insight-ghidra/references/research.md +87 -0
  87. package/skill-bundle/insight-ghidra/references/setup.md +1 -1
  88. package/skill-bundle/insight-ghidra/references/sparse-navigation.md +173 -0
  89. package/skill-bundle/insight-ilspy/SKILL.md +1 -1
  90. package/skill-bundle/insight-interop/SKILL.md +1 -1
  91. package/skill-bundle/insight-lldb/SKILL.md +1 -1
  92. package/skill-bundle/insight-llvm/SKILL.md +1 -1
  93. package/skill-bundle/insight-managed-heap/SKILL.md +1 -1
  94. package/skill-bundle/insight-managed-metadata/SKILL.md +1 -1
  95. package/skill-bundle/insight-mitmproxy/SKILL.md +1 -1
  96. package/skill-bundle/insight-overview/SKILL.md +1 -1
  97. package/skill-bundle/insight-procmon/SKILL.md +1 -1
  98. package/skill-bundle/insight-re/SKILL.md +4 -1
  99. package/skill-bundle/insight-re/references/persistent-client.mjs +125 -0
  100. package/skill-bundle/insight-re/references/persistent.md +50 -0
  101. package/skill-bundle/insight-re/references/recovery.md +36 -0
  102. package/skill-bundle/insight-sevenzip/SKILL.md +1 -1
  103. package/skill-bundle/insight-strace/SKILL.md +1 -1
  104. package/skill-bundle/insight-tshark/SKILL.md +1 -1
  105. package/skill-bundle/insight-windbg/SKILL.md +1 -1
  106. package/skill-bundle/manifest.json +1 -1
  107. package/skills/insight-artifacts/SKILL.md +1 -1
  108. package/skills/insight-artifacts/references/recovery.md +36 -0
  109. package/skills/insight-binary/SKILL.md +1 -1
  110. package/skills/insight-capture/SKILL.md +1 -1
  111. package/skills/insight-die/SKILL.md +1 -1
  112. package/skills/insight-dnspy/SKILL.md +1 -1
  113. package/skills/insight-dotnet-dump/SKILL.md +1 -1
  114. package/skills/insight-dotnet-stack/SKILL.md +1 -1
  115. package/skills/insight-dotnet-trace/SKILL.md +1 -1
  116. package/skills/insight-frida/SKILL.md +1 -1
  117. package/skills/insight-ghidra/SKILL.md +14 -1
  118. package/skills/insight-ghidra/references/persistent-client.mjs +125 -0
  119. package/skills/insight-ghidra/references/persistent.md +50 -0
  120. package/skills/insight-ghidra/references/query-semantics.md +12 -0
  121. package/skills/insight-ghidra/references/recovery.md +36 -0
  122. package/skills/insight-ghidra/references/research.md +87 -0
  123. package/skills/insight-ghidra/references/setup.md +1 -1
  124. package/skills/insight-ghidra/references/sparse-navigation.md +173 -0
  125. package/skills/insight-ilspy/SKILL.md +1 -1
  126. package/skills/insight-interop/SKILL.md +1 -1
  127. package/skills/insight-lldb/SKILL.md +1 -1
  128. package/skills/insight-llvm/SKILL.md +1 -1
  129. package/skills/insight-managed-heap/SKILL.md +1 -1
  130. package/skills/insight-managed-metadata/SKILL.md +1 -1
  131. package/skills/insight-mitmproxy/SKILL.md +1 -1
  132. package/skills/insight-overview/SKILL.md +1 -1
  133. package/skills/insight-procmon/SKILL.md +1 -1
  134. package/skills/insight-re/SKILL.md +4 -1
  135. package/skills/insight-re/references/persistent-client.mjs +125 -0
  136. package/skills/insight-re/references/persistent.md +50 -0
  137. package/skills/insight-re/references/recovery.md +36 -0
  138. package/skills/insight-sevenzip/SKILL.md +1 -1
  139. package/skills/insight-strace/SKILL.md +1 -1
  140. package/skills/insight-tshark/SKILL.md +1 -1
  141. package/skills/insight-windbg/SKILL.md +1 -1
@@ -51,6 +51,18 @@ finding. Narrow the query or raise its budget within the declared bound. Oversiz
51
51
  also stop a scan rather than silently claiming complete coverage. Returned string values are
52
52
  bounded; check truncation fields.
53
53
 
54
+ `strings list` and `strings search` visit **defined data**, not every possible literal in memory.
55
+ The visited-input budget includes non-string data. Zero matches with an incomplete scan means
56
+ the searched prefix contains no matches; it does not establish absence. Increasing `--offset`
57
+ only skips matching rows from that same scan and cannot reach a later unscanned string. These
58
+ scans have no continuation cursor. Increase `--max-scan` up to 200000 when that covers the
59
+ needed data. A narrower text filter alone does not skip earlier visited data or reach beyond
60
+ that bound; use an explicitly addressed memory search when the needed region is known.
61
+ For undefined ASCII/UTF-16 literals, encode the expected bytes and use
62
+ `analysis search-byte-patterns --pattern <hex> --max-bytes <bytes>`; that separate initialized-
63
+ memory search exposes `--scan-from`/`next_address` continuation. Byte matches still need
64
+ interpretation and do not define string data or prove a stored xref exists.
65
+
54
66
  Bounded string/instruction regex search supports literals, escapes, anchors, character classes
55
67
  and at most one `.*` wildcard. Branching/nested repetition and unsupported patterns are rejected.
56
68
  Use the literal `strings search --contains` convenience when no regex is needed.
@@ -24,11 +24,47 @@ establishes that the old owned bootstrap worker has ended, then uses an authorit
24
24
  probe. An absent canonical item permits private preparation; an existing first version requires
25
25
  independent readback. The old project, intent and original session/target remain preserved.
26
26
 
27
+ ## Interrupted save or close
28
+
29
+ After restoring profile storage, inspect the selected session and target with
30
+ `sessions status <session> --target <target>`. Retry the original save/close with the
31
+ same `--request-id`. If the original command had no caller ID, use the generated
32
+ `unresolvedRequests[].id` from status. This retrieves the original intent instead of
33
+ creating another close. A verified stopped worker lets close report `state: closed`
34
+ and retain the acknowledged private snapshot and pending changes; it sends no new save,
35
+ open, close or publication. Reopen the same session/target afterward.
36
+
37
+ If release cannot be proved, the command still fails with `coordinator.unknown`
38
+ and gives scoped status/process inspection commands. An authenticated live worker is not
39
+ closed again automatically. Retain its project and journals. After inspecting its retained
40
+ work, an operator may terminate that exact owned headless worker through
41
+ `tools processes kill <process>` with Destructive permission, accepting loss of any
42
+ unacknowledged in-memory work. Do not kill by guessed PID/port or stop the shared server.
43
+ Retrieve the same close request after that worker has ended. An unavailable endpoint or
44
+ changed process receipt is not proof of release; preserve the binding for investigation.
45
+
27
46
  If a response was lost, inspect `sessions status <session> --target <target>`. Never infer
28
47
  `applied` from a connection failure. A changing command's optional request ID binds one effective
29
48
  intent inside the profile. Repeating the same ID/input retrieves its recorded outcome or
30
49
  unresolved state; changing input under that ID fails. Without an ID, calls are new intentions.
31
50
 
51
+ For Java `scripts run-inline`, a versioned native executor records compilation, non-initializing
52
+ class resolution, initialization, construction and framework execution separately. A correlated
53
+ receipt proving `userCode: not_started` and `entrypointInvoked: false` before initialization
54
+ produces `state: rejected` with a terminal failed request. The context remains available and
55
+ its prior saved/pending work is unchanged. The CLI exits nonzero; the error result retains
56
+ bounded compiler/load diagnostics. Repeating that request ID retrieves the same rejection;
57
+ corrected source requires a new ID. Each attempt has isolated source/classes under profile
58
+ analysis storage, with annotation processing disabled and no reuse of older inline classes.
59
+
60
+ Initialization or constructor failure can have effects even when `run()` was never called.
61
+ These failures, framework/runtime failures and missing/malformed/lost acknowledgements remain
62
+ unknown. During framework execution `entrypointInvoked: null` means actual `run()` entry was
63
+ not independently observed. Console text cannot establish non-execution. This is not a sandbox
64
+ for adversarial same-JVM Java, and existing unknown script attempts are not reclassified from
65
+ their exception strings or an unchanged program snapshot. File/Python scripts retain their
66
+ existing conservative recovery semantics.
67
+
32
68
  An unknown or partial effect retains its request intent, snapshots and native stage. Open the
33
69
  same tuple to reconcile supported outcomes. A committed merge is verified against its recorded
34
70
  server version and complete saved buffers through independent read authority; it is never
@@ -17,6 +17,13 @@ Open input with `insight-cli ghidra open ./client.exe --session new --json`. Sto
17
17
  `session` and `target` as the explicit scope for every later research call. Names are display
18
18
  labels; equal filenames or addresses in different inputs do not select the same object.
19
19
 
20
+ If the database has missing strings/xrefs, one-byte function bodies or no Listing instructions,
21
+ use [sparse navigation](sparse-navigation.md) before following the metadata-only route below.
22
+ It distinguishes existing entries, undefined code and undefined literals. For raw literals,
23
+ use `strings anchors --text Widget --encodings ascii,utf16le --scan-from START --scan-through END`,
24
+ then explicit batched code references and function inspection. Candidate context remains
25
+ separate from exact match addresses; coverage, decoding, caps and cursor are explained there.
26
+
20
27
  Use `ghidra strings search --contains config.json`, then `ghidra xrefs to --address <string>`.
21
28
  Reference results include a containing function address when available. Pass that address to
22
29
  `ghidra functions get` or `ghidra functions decompile`. Add the same session/target selectors and
@@ -105,6 +112,19 @@ native, a sanitized diagnostic of at most 500 Unicode characters. Reasons distin
105
112
  `function_not_found`, `native_function_failure`, `selector_mismatch`, `invalid_native_shape`,
106
113
  `missing_signature` and `missing_decompiler_text`. Missing definitions remain failures; reads
107
114
  never create functions or run analysis. JSON-RPC `cli.execute` preserves the same error data.
115
+ If executable bytes are known but the function is absent, use the read-only `functions decode`
116
+ command below at the explicit address. A containing function with a one-byte body and missing
117
+ stored xrefs can also indicate sparse metadata. Decode reveals bounded local instruction flow;
118
+ it does not repair function boundaries or establish whole-function callers/callees. Defining
119
+ functions or disassembling the listing requires a separate explicit Update operation.
120
+ For a known existing entry, try compact `functions inspect` first; use
121
+ `functions force-decompile --function <entry>` to refresh stale/failed decompiler output.
122
+ Its result is `value.decompiled`, and its pinned upstream work bound is not guaranteed.
123
+ Successful transient decompilation can coexist with an empty Listing and missing stored xrefs.
124
+ It does not create an absent function or repair its saved body. Avoid repeating it merely to
125
+ populate `functions disassemble`; use bounded `decode` for local instruction corroboration.
126
+ Per-item inspection failures retain the facade recovery message in `error` and the bounded
127
+ native explanation separately in `nativeDiagnostic`; use stable `reason` for classification.
108
128
 
109
129
  The existing `functions inspect` accepts 1–20 distinct names/addresses. Existing `--fields`
110
130
  remain valid; unknown fields fail before dispatch. Decompiled text uses per-item
@@ -129,6 +149,32 @@ host, including through JSON-RPC; it is never silently a client-host path. An ex
129
149
  is rejected. A filesystem failure can leave a partial new directory without a completed manifest;
130
150
  retain it for inspection and choose a fresh directory for another explicit save.
131
151
 
152
+ For sparse interior addresses, opt in to
153
+ `functions inspect --functions <hex-addresses> --resolve-address containing-or-preceding --max-entry-distance 4096`.
154
+ The distance is required (1–65536 bytes), applies only to fallback and is rejected without the
155
+ mode. Names/address-space prefixes are not accepted in this mode. Exact entries and recorded
156
+ body containment take precedence in valid default-space memory, including non-executable or
157
+ uninitialized blocks. Otherwise the nearest previous known entry is considered only inside
158
+ the same initialized executable memory block as the query.
159
+ No byte search, analysis or function creation is performed.
160
+
161
+ Every resolved row retains `entry_point` and `resolution`, even if `--fields` omits entry metadata
162
+ or the function read fails. Kinds are `exact-entry`, `recorded-containing` and
163
+ `preceding-entry-candidate`. `recordedBodyContainsAddress` is actual stored body membership,
164
+ not semantic proof. `distanceBytes` is zero for exact entries and the positive offset for
165
+ preceding candidates; it is omitted for recorded containment, whose body can precede its entry.
166
+ `status: success` means the selected function was read, not that the query belongs to it.
167
+
168
+ `--functions` preserves original selector spelling as keys, including hexadecimal aliases.
169
+ Selected entries are deduplicated for native reads, but inline text is charged for every
170
+ original row in selector order. Each saved row keeps its mapping; owner-save paths remain
171
+ per-selector. `--function` retains the existing single-row result/error behavior. Policy misses
172
+ are per-item `not_found` with `address_out_of_range`,
173
+ `address_not_in_initialized_executable_block`, `no_preceding_entry`, `entry_outside_block` or
174
+ `entry_distance_exceeded`; these do not claim that code or an unknown function is absent.
175
+ The before/after guard covers both lookup and inspection, and native selector/entry mismatches
176
+ fail. Existing view continuation/text hashes, text windows and result/file bounds still apply.
177
+
132
178
  `functions decode --address <address> --max-bytes 64 --max-instructions 16` uses Ghidra pseudo
133
179
  instructions without defining listing instructions, functions or xrefs, running analyzers or
134
180
  saving state. It requires initialized executable memory and currently supports x86 language
@@ -139,3 +185,44 @@ computed from instruction bytes, not proof of function membership or stored xref
139
185
  flow has no invented target. Decoding stops at terminal/unconditional flow, input/instruction
140
186
  bounds, undecodable/truncated bytes or unavailable context. Existing `disassemble-bytes` remains
141
187
  an Update operation with its original guards.
188
+
189
+ ## Navigation and lifecycle diagnostics
190
+
191
+ `analysis navigation` uses the selected session/target and ReadOnly permission. It reports
192
+ `initialAnalysis` (`none` or `requested`) as the original facade import policy, separately from
193
+ the current metadata observations. Prior analysis history is unknown, including saved/imported
194
+ databases. `ready` means the context opened; it does not establish analysis completeness.
195
+
196
+ The diagnostic samples at most 128 functions, instructions, stored references and defined-data
197
+ units per category, in address order, sharing `--max-scan` (default 10000, 1–200000) and a fixed
198
+ five-second native deadline. Each category reports its own completion; top-level `scan` reports
199
+ the visited sum, sample bound, completion and reason. Defined-string counts cover only sampled
200
+ defined data. One-byte bodies together with missing entry instructions in at least 80% of the
201
+ sample yield `sparse-metadata`; this is an explicit heuristic, not proof that a specific analysis
202
+ pass failed. Normal instruction-bearing one-byte leaf functions alone do not trigger it.
203
+ Follow [sparse navigation](sparse-navigation.md): known function entries can use compact inspection
204
+ and cache refresh; executable bytes without an entry use bounded decode, undefined literals use
205
+ byte search and explicit continuation. The diagnostic does
206
+ not run analyzers, define data, repair boundaries, save a snapshot or certify semantic completeness.
207
+
208
+ `diagnostics lifecycle` reads retained start/restore/stop events and the current process receipt
209
+ without starting or probing Ghidra. At most the latest 128 observations are retained. A stopped
210
+ receipt can identify `explicit_close`, `view_replaced`, `mode_changed`, `startup_failed` or
211
+ `owner_dispose`; historical receipts without reasons remain `unknown`. Owner disposal does not
212
+ establish whether Factory exited due to idle, explicit stop, a signal or another cause. A current
213
+ receipt without a matching stop receipt reports `unobserved`, not a claim that the PID is live.
214
+
215
+ Internal correlated timing diagnostics live under profile workspace `diagnostics/timings.jsonl`,
216
+ with one previous segment and an eight-MiB rotation threshold. They contain operation names,
217
+ timestamps, correlation/parent IDs, duration and success/failure, not argv, source, payloads or
218
+ exception text. They are an internal troubleshooting format, not a public trace API. Nested spans
219
+ must not be added to their parents. `facade.command` starts at the handler and ends before Factory
220
+ serializes the response; client startup, IPC and response overhead are not separately measured.
221
+ Tracing is best-effort and cannot change program outcomes. Empty runtime readiness checks still
222
+ avoid creating a research workspace. The Factory idle policy remains unchanged.
223
+
224
+ For sparse PE32+/AMD64 interior addresses, `functions inspect --resolve-address
225
+ containing-or-pe-runtime --max-unwind-bytes 4194304` uses fully validated current mapped runtime
226
+ regions and independent recorded-body facts. Conflicting or missing entries remain partial with
227
+ evidence; incomplete/malformed/unavailable metadata prevents automatic selection. This is not
228
+ semantic function reconstruction; see [sparse navigation](sparse-navigation.md).
@@ -11,7 +11,7 @@ external executable paths, status/doctor and safe removal. Existing Factory prof
11
11
  The package contains the verified GhidraMCP 7.0.0 bridge, its Apache-2.0 license/notice and
12
12
  artifact provenance. Its pinned functionality catalog is from source
13
13
  `57e37a8bf388b1279cff46378f85be1554548f61`, with SHA256
14
- `7084e2fda16dc779dd05398e48821ff3f9ace4d32757ea143b257b39689e5fbd`.
14
+ `f4a9272e911466ed774c8cf73bc1adf1daef6009d895fda57aa0b28522fcdf32`.
15
15
  `mcpJar` optionally selects another copy of those exact verified bytes. Runtime startup needs no
16
16
  bridge/Factory source checkout or Python MCP bridge. Packaged native helper sources compile
17
17
  against the installed Ghidra/JDK.
@@ -0,0 +1,173 @@
1
+ # Navigate a sparse database
2
+
3
+ Function counts and `ready` do not establish decoded bodies, strings or xrefs. A one-byte
4
+ function entry without Listing instructions can still be useful to the decompiler. Choose
5
+ the route from the actual observation before building a script or requesting broad analysis.
6
+
7
+ All examples below need the same `--session S --target T --json`. Replace placeholder
8
+ addresses with observed addresses in that input; symbols and offsets never transfer implicitly.
9
+ Use generated help for exact flags.
10
+
11
+ | Observation | Next command | What it establishes |
12
+ |---|---|---|
13
+ |Empty navigation results / suspicious body sizes|`analysis navigation`|Bounded metadata samples and coverage; no analysis is started|
14
+ |Known function entries, even without Listing|`functions inspect --functions 0xENTRY_A,0xENTRY_B --fields decompiled_code,callees --include-call-context false`|Up to20 compact decompiler observations; inspect each status and truncation|
15
+ |Interior code addresses with sparse saved bodies|`functions inspect --functions 0xCODE_A,0xCODE_B --resolve-address containing-or-preceding --max-entry-distance 4096 --fields entry_point,decompiled_code --include-call-context false`|One guarded lookup+inspection; a preceding entry is explicitly a candidate, not established containment|
16
+ |Stale/failed decompilation at a known entry|`functions force-decompile --function 0xENTRY`|Fresh native decompiler output in `value.decompiled`; no function creation or Listing repair|
17
+ |Known executable bytes, no function entry|`functions decode --address 0xCODE --max-bytes 64 --max-instructions 16`|Bounded local instructions/direct targets, input hash and stop reason; no persistent definitions|
18
+ |Expected literal absent from defined strings|`strings anchors --text SPARSE --encodings ascii,utf16le --scan-from 0xREGION_START --scan-through 0xREGION_END`|Exact raw hits plus separate bounded NUL candidate context, explicit coverage and stateless cursor|
19
+
20
+ ## Follow existing entries first
21
+
22
+ Start with a small set of independently known entries: exported symbols, retained project
23
+ evidence for this exact build or direct targets from bounded decode. Check the function selector;
24
+ an interior address is not automatically an entry. Compact inspection avoids unrelated metadata
25
+ and supports mixed outcomes, text paging and owner-host saves. For large output, use
26
+ `--save-owner-directory <new-absolute-directory>` and retain its hash manifest; see
27
+ [research](research.md) for Unicode windows, view guards and native truncation.
28
+ Empty `callees` or xrefs on a sparse database do not prove that the decompiled function
29
+ has no calls. Keep decompiler observations distinct from stored-reference coverage.
30
+
31
+ For known interior addresses, the explicit resolution mode avoids the separate name/prefix
32
+ search. It accepts addresses only and requires the distance bound. Inspect `resolution.kind`
33
+ for every result: `exact-entry`, `recorded-containing`, or `preceding-entry-candidate`.
34
+ Recorded containment is a database fact, not validated source membership. The fallback may
35
+ point into unrelated padding, split code or an incorrect prior function. It is not a repair.
36
+ Exact/recorded containment take precedence; the distance limit applies only to fallback.
37
+ See [research](research.md) for mixed outcomes, original selector keys and shared budgets.
38
+
39
+ Use `force-decompile` when a fresh decompiler pass is needed. It does not accept the inspect
40
+ text-window/save flags; its ordinary query response is capped at1MiB and reports the pinned
41
+ upstream work bound as not guaranteed. Selecting one entry narrows the request but is not a
42
+ hard instruction/CPU bound. A host running-session ID must be awaited, not retried as failure.
43
+ No successful decompile is proof of complete control flow, correct types or valid function bounds.
44
+
45
+ After transient decompilation, `functions disassemble`, instruction search and stored xrefs can
46
+ remain empty. Repeating cache refresh does not populate them. Corroborate an important store,
47
+ branch or call with bounded `decode` at its observed instruction address. Its direct targets are
48
+ local decoded flow, not a complete call graph. Neither route runs the target program.
49
+
50
+ ## When entries or literals are absent
51
+
52
+ An absent function stays absent after `force-decompile`. Use bounded decode, retaining its
53
+ stop reason; do not silently create functions to make a read succeed. Decode stops at terminal
54
+ or unconditional flow and has byte/instruction limits; it is not whole-function reconstruction.
55
+ Persistent Listing/entry/body repair is a separate explicit Update operation in the owned
56
+ context, followed by saved readback. Consult `functions create`, `functions disassemble-bytes`
57
+ and their generated help rather than an unbounded all-function reconstruction script.
58
+
59
+ For literal search, prefer `strings anchors` with explicit encodings and both inclusive bounds.
60
+ It searches raw initialized bytes, merges adjacent initialized blocks, and never bridges a hole.
61
+ Read `matchAddress` as the exact target; a nullable candidate `start` is a separate observation.
62
+ NUL candidates are not semantic strings. `textFrom` is the preview address; `complete`,
63
+ boundary evidence and `decoding` qualify it. Invalid or capped context keeps the raw hit.
64
+ Continue using `value.cursor`; only page budgets can change. `scan.complete` refers to search
65
+ coverage, not complete candidate text. Context/prefetch/rereads consume `max-bytes` (minimum
66
+ 32768), and the default payload cap is 1024 bytes. Retain all `(address,encoding)` pairs,
67
+ including overlaps and UTF-16 at odd addresses. It performs no definitions, analysis or save.
68
+ Then pass selected exact match addresses to one batched `analysis code-references`, and
69
+ selected code addresses to `functions inspect` with the explicit resolution mode above.
70
+
71
+ For arbitrary masked binary patterns, encode ASCII/UTF-16 as appropriate with the existing
72
+ `analysis search-byte-patterns`; for example `--pattern '53 50 41 52 53 45'` is ASCII `SPARSE`.
73
+ Quote spaced hex patterns. Read `complete`, `scanned_bytes`, `next_address` and the bounds;
74
+ continue with `--scan-from <next_address>`. `--offset` on defined-string results does not
75
+ advance memory coverage. A narrowed text filter does not skip earlier non-string defined data.
76
+ Use `memory list` to identify initialized/executable blocks; do not assume a guessed block name
77
+ or that the image-base address belongs to executable code.
78
+
79
+ Byte matches are not validated code references. Existing xrefs describe saved DB metadata.
80
+ For exact RIP-relative operands or direct CALL destinations, use the bounded ReadOnly candidate
81
+ scanner below. Arbitrary scripts remain potential writes with saved-state/recovery costs;
82
+ a compile/transport error must not be blindly replayed.
83
+
84
+ ## Raw-byte code-reference candidates (V1)
85
+
86
+ ```sh
87
+ insight-cli ghidra analysis code-references --session S --target T \
88
+ --to 180080000,180080008 --forms call-rel32,lea-rip,mov-rip,call-rip-slot \
89
+ --scan-from 180000000 --scan-through 18002101f --limit 100 --json
90
+ ```
91
+
92
+ `value.matches` contains instruction bytes, full length, operand index/width, exact target,
93
+ form, native instruction text and boundary evidence. Example row:
94
+
95
+ ```json
96
+ {"from":"180000060","to":"180080008","form":"call-rip-slot","bytes":"ff15a2ff0700","length":6,"operand_index":0,"operand_bits":64,"target_role":"pointer-slot","validation":"decoded","boundary":"unconfirmed","instruction":"CALL qword ptr [0x180080008]"}
97
+ ```
98
+
99
+ Targets are
100
+ 1–64 distinct default-space unsigned 64-bit addresses, comma separated; they share one pass.
101
+ Only x86 little-endian 64-bit languages with known 64-bit decode mode are supported. No code
102
+ executes, and no Listing instructions, functions or xrefs are created. This does not follow
103
+ register values, indirect callees, thunks, pointer contents or control flow.
104
+
105
+ | Form | Supported encoding | Target role |
106
+ |---|---|---|
107
+ | `call-rel32` | E8 + signed rel32 | `direct-call-target` |
108
+ | `lea-rip` | 8D, ModRM RIP-relative | `effective-address` |
109
+ | `mov-rip` | GPR MOV 88/89/8A/8B, ModRM RIP-relative | `effective-address` |
110
+ | `call-rip-slot` | FF /2, ModRM RIP-relative | `pointer-slot` |
111
+
112
+ Forms default to all four; `--forms` restricts them. Legacy 66/26/2E/36/3E and REX prefixes
113
+ are admitted only when the native full decode agrees with the constrained encoding/length.
114
+ REX before a later legacy prefix is reset. Widths are explicit: `lea eax` and `lea rax` remain
115
+ distinct. V1 excludes 67 address override, FS/GS, LOCK/REP, C6/C7 immediate MOV,
116
+ MOVSX/MOVZX/MOVSXD and SIMD/VEX/EVEX **at that candidate start**. A later byte inside any
117
+ instruction or immediate can independently decode as a supported candidate.
118
+
119
+ Each byte offset is tested, including overlapping and prefix-alternative starts; advancement
120
+ is one byte. `listing-confirmed` requires a matching stored instruction and compatible bytes,
121
+ length and operand display. `listing-conflict` means overlap/disagreement with a stored
122
+ instruction. `unconfirmed` means neither. Even listing-confirmed is not proof of execution,
123
+ function membership or a complete call graph. LEA is an effective address, not a memory read.
124
+
125
+ `--scan-through` is the inclusive final byte, and each match fits entirely inside the original
126
+ range. Only initialized executable default-space memory is visited. Adjacent eligible blocks
127
+ merge so an instruction may cross their boundary; holes, uninitialized blocks and non-executable
128
+ memory never bridge. A complete scan only exhausts this declared eligible input/form set.
129
+
130
+ `value.scan` reports `bytes_read` (including lookahead and rereads), `tested_starts`,
131
+ `visited_candidates` (selected-form encoding prefilter hits, including target/decode rejects),
132
+ `next_start` (first unchecked start), `complete`, `reason` and native `elapsed_ms`.
133
+ The frontier can skip ineligible gaps; it does not assert that gap bytes were decoded.
134
+ Reasons are `exhausted`, `byte_limit`, `candidate_limit`, `timeout` and `result_limit`.
135
+ The native cooperative deadline is checked even in no-match regions. Compile/dispatch/view
136
+ observation time is outside that deadline; it remains part of command wall time.
137
+
138
+ Defaults: 4MiB bytes, 200000 candidates, 5 seconds and 100 matches. Maxima: 16MiB,
139
+ 1000000 candidates, 30 seconds and 1000 matches. Minimum byte budget is15, so a maximum-length
140
+ x86 start can progress with its lookahead. No semantic completeness is implied by these limits.
141
+
142
+ For an incomplete result, continue with the opaque stateless token:
143
+
144
+ ```sh
145
+ insight-cli ghidra analysis code-references --session S --target T \
146
+ --cursor TOKEN --limit 1000 --max-bytes 8388608 --json
147
+ ```
148
+
149
+ Cursor excludes `--to`, `--forms`, `--scan-from` and `--scan-through`; omitted controls inherit
150
+ the previous page. It binds the normalized original query, frontier, algorithm version, selected
151
+ context/snapshot/generation, native modification observation and process incarnation. Scope,
152
+ format or version mismatch fails; view changes, including restoring the same snapshot in a new
153
+ JVM, fail with `changed_view`. Start a new query after such a change. Before/after observations
154
+ share the context's ordered action; a native modification guard additionally covers the scan.
155
+
156
+ Tokens are unsigned, untrusted continuation parameters, not evidence that earlier offsets were
157
+ scanned. There is no cursor registry, per-query snapshot or journal save. Retain page results
158
+ if coverage evidence is needed. The trusted helper still uses the existing inline-script
159
+ transport and incurs its compile/dispatch cost; arbitrary user scripts remain Update operations.
160
+
161
+ ## PE runtime regions for sparse function inspection
162
+
163
+ Use `ghidra functions inspect --functions <addresses> --resolve-address containing-or-pe-runtime`
164
+ when PE32+/AMD64 runtime metadata can replace manual preceding-entry checks.
165
+ `--max-unwind-bytes` bounds returned header/table bytes across the batch (default4194304,
166
+ 1–16777216); lookup has a fixed5-second cooperative deadline. It reads current mapped headers
167
+ at the actual image base and the whole declared Exception Directory, without a file fallback,
168
+ section-name assumption, analysis or function creation. Unavailable/malformed/incomplete lookup
169
+ blocks selection and retains DB facts; `boundary_conflict` and `runtime_entry_not_defined` retain
170
+ validated bounds. A runtime region does not prove instruction boundaries, semantic membership
171
+ or whole-function bounds; leaf routines may have no record. No preceding fallback is used.
172
+ Batch unresolved rows are partial; a single unresolved selector returns a partial CLI error
173
+ with lookup/view/evidence. Guards cover failed dispatch; existing text paging/save rules apply.
@@ -3,7 +3,7 @@ name: insight-ilspy
3
3
  description: Recover C#, inspect IL/types/metadata, extract resources or export projects from managed .NET assemblies through insight-cli ILSpy. Choose native analysis for NativeAOT or ordinary PE machine code.
4
4
  ---
5
5
 
6
- # Insight ILSpy 0.3.2
6
+ # Insight ILSpy 0.4.1
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-interop
3
3
  description: Trace a .NET P/Invoke declaration to an explicitly supplied native library export and Ghidra function through insight-cli ilspy query, binary query and scoped ghidra APIs. Use for managed/native linkage evidence while keeping static correspondence separate from observed loading or execution.
4
4
  ---
5
5
 
6
- # Insight Interop 0.3.2
6
+ # Insight Interop 0.4.1
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-lldb
3
3
  description: Observe native runtime arguments, return values, registers, stacks and bounded memory at a selected breakpoint using an owned LLDB launch. Use insight-cli lldb on macOS ARM64 when static findings need a concrete execution check.
4
4
  ---
5
5
 
6
- # Insight LLDB 0.3.2
6
+ # Insight LLDB 0.4.1
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-llvm
3
3
  description: Inspect PE, ELF and Mach-O headers, dependencies, exports and symbols; query PDB debug information or a small instruction window with insight-cli LLVM utilities before opening a full analysis project.
4
4
  ---
5
5
 
6
- # Insight LLVM 0.3.2
6
+ # Insight LLVM 0.4.1
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-managed-heap
3
3
  description: Query structured .NET heap objects, primitive fields and managed stacks from a retained CoreCLR dump through insight-cli dotnet-dump query. Use for bounded offline dump investigation with an explicit matching DAC, preserving uncertainty and immutable input identity.
4
4
  ---
5
5
 
6
- # Insight Managed Heap 0.3.2
6
+ # Insight Managed Heap 0.4.1
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-managed-metadata
3
3
  description: Query managed assembly metadata, MethodDef tokens, P/Invoke declarations and bounded IL, or compare two C#/.NET assemblies through insight-cli ilspy query/compare. Use for structured static evidence and changed-method research without executing the target.
4
4
  ---
5
5
 
6
- # Insight Managed Metadata 0.3.2
6
+ # Insight Managed Metadata 0.4.1
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-mitmproxy
3
3
  description: Record, inspect and compare HTTP request/response evidence with insight-cli mitmproxy. Use when an owned client can explicitly use a loopback proxy; read native flow archives or HAR without replaying traffic. System interception and global certificate trust are outside this facade.
4
4
  ---
5
5
 
6
- # Insight mitmproxy 0.3.2
6
+ # Insight mitmproxy 0.4.1
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-overview
3
3
  description: Choose bounded tool overviews and focused drilldown through insight-cli without flooding agent context with whole-program code, traces or dumps. Use for tool discovery, scoped evidence paging and keeping native partial coverage separate from complete results.
4
4
  ---
5
5
 
6
- # Insight Overview 0.3.2
6
+ # Insight Overview 0.4.1
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-procmon
3
3
  description: Observe actual file and registry access by an authorized running Windows process through insight-cli procmon. Use when static paths or configuration guesses need runtime evidence; inspect retained captures without collecting again.
4
4
  ---
5
5
 
6
- # Insight ProcMon 0.3.2
6
+ # Insight ProcMon 0.4.1
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -3,7 +3,7 @@ name: insight-re
3
3
  description: Investigate shipped programs and binary artifacts with insight-cli and other available tools; retain ordinary research files, coordinate independent agents and publish Ghidra annotations. Use for reverse engineering behavior, not ordinary source-repository browsing.
4
4
  ---
5
5
 
6
- # Insight RE 0.3.2
6
+ # Insight RE 0.4.1
7
7
 
8
8
  If local help/status reports AppData or IPC access denied, retry that **read-only probe**
9
9
  with the agent host's normal permission escalation, then use that route for later authorized
@@ -14,6 +14,9 @@ request/status recovery, never blind retry.
14
14
 
15
15
  Answer the user's research question with inspectable materials. Agents choose the
16
16
  investigation; insight-cli supplies applications such as `ghidra` and `artifacts`.
17
+
18
+ For repeated facade queries, retain one [persistent client](references/persistent.md) in the
19
+ agent runtime across calls. Follow its typed command errors and uncertain-transport recovery.
17
20
  External tools need no insight-cli adapter. Installing this package does not register
18
21
  the skill or change agent settings. `insight-cli skill insight-re` locates this file.
19
22
 
@@ -0,0 +1,125 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { StringDecoder } from 'node:string_decoder';
3
+ export class InsightCommandError extends Error {
4
+ rpc;
5
+ constructor(rpc) {
6
+ super(rpc.message);
7
+ this.rpc = rpc;
8
+ this.name = 'InsightCommandError';
9
+ }
10
+ }
11
+ export class InsightTransportError extends Error {
12
+ dispatched;
13
+ constructor(message, dispatched) {
14
+ super(message);
15
+ this.dispatched = dispatched;
16
+ this.name = 'InsightTransportError';
17
+ }
18
+ }
19
+ /** A thin client of Factory's existing stream, with no reconnect or command replay. */
20
+ export async function connectInsight(options) {
21
+ const child = spawn(options.executable, [...(options.arguments ?? []), '--json-rpc'], { cwd: options.cwd, env: options.env, stdio: ['pipe', 'pipe', 'pipe'], shell: false });
22
+ const maximum = 4 * 1024 ** 2, decoder = new StringDecoder('utf8');
23
+ let buffer = '', bytes = 0, sequence = 0, accepting = true, failed = false, ended = false;
24
+ let closePromise, tail = Promise.resolve();
25
+ const pending = new Map();
26
+ // Drain diagnostics without retaining arbitrary stderr, paths, tokens or unbounded output.
27
+ child.stderr.resume();
28
+ const fail = (message) => {
29
+ if (failed)
30
+ return;
31
+ failed = true;
32
+ accepting = false;
33
+ for (const p of pending.values())
34
+ p.reject(new InsightTransportError(message, true));
35
+ pending.clear();
36
+ child.stdin.destroy();
37
+ child.stdout.destroy();
38
+ };
39
+ child.on('error', () => fail('Persistent CLI process failed.'));
40
+ child.stdout.on('error', () => fail('Persistent CLI output was lost.'));
41
+ child.stderr.on('error', () => fail('Persistent CLI diagnostic stream was lost.'));
42
+ child.stdin.on('error', () => fail('Persistent CLI input was lost; inspect request/status before retrying a changing command.'));
43
+ const exited = new Promise((resolve, reject) => {
44
+ child.once('close', (code, signal) => {
45
+ ended = true;
46
+ if (code !== 0 || signal || pending.size || buffer.trim()) {
47
+ fail('Persistent CLI closed without a complete acknowledged response.');
48
+ reject(new InsightTransportError('Persistent CLI transport ended unexpectedly.', false));
49
+ }
50
+ else if (failed)
51
+ reject(new InsightTransportError('Persistent CLI transport failed.', false));
52
+ else
53
+ resolve();
54
+ });
55
+ });
56
+ void exited.catch(() => { });
57
+ child.stdout.on('data', (chunk) => {
58
+ if (failed)
59
+ return;
60
+ buffer += decoder.write(chunk);
61
+ bytes += chunk.length;
62
+ if (bytes > maximum) {
63
+ fail('Persistent CLI response exceeded the bounded transport limit.');
64
+ return;
65
+ }
66
+ for (;;) {
67
+ const newline = buffer.indexOf('\n');
68
+ if (newline < 0)
69
+ break;
70
+ const line = buffer.slice(0, newline);
71
+ buffer = buffer.slice(newline + 1);
72
+ bytes = Buffer.byteLength(buffer);
73
+ if (!line.trim())
74
+ continue;
75
+ try {
76
+ const r = JSON.parse(line);
77
+ if (!r || r.jsonrpc !== '2.0' || typeof r.id !== 'number' || !pending.has(r.id) || Object.hasOwn(r, 'result') === Object.hasOwn(r, 'error'))
78
+ throw Error();
79
+ const p = pending.get(r.id);
80
+ if (Object.hasOwn(r, 'error') && (!r.error || typeof r.error !== 'object' || typeof r.error.code !== 'number' || !Number.isInteger(r.error.code) || typeof r.error.message !== 'string'))
81
+ throw Error();
82
+ pending.delete(r.id);
83
+ if (r.error)
84
+ p.reject(new InsightCommandError(r.error));
85
+ else
86
+ p.resolve(r.result);
87
+ }
88
+ catch {
89
+ fail('Persistent CLI returned a malformed or uncorrelated response.');
90
+ return;
91
+ }
92
+ }
93
+ });
94
+ await new Promise((resolve, reject) => { child.once('spawn', resolve); child.once('error', () => reject(new InsightTransportError('Could not start persistent CLI.', false))); });
95
+ return {
96
+ execute(argv) {
97
+ if (!Array.isArray(argv) || argv.length > 512 || argv.some(x => typeof x !== 'string' || x.includes('\0')) || Buffer.byteLength(JSON.stringify(argv)) > 1024 ** 2)
98
+ return Promise.reject(new TypeError('argv must be a bounded array of strings without NUL.'));
99
+ if (!accepting || failed || ended)
100
+ return Promise.reject(new InsightTransportError('Persistent CLI connection is closed.', false));
101
+ const args = [...argv];
102
+ const request = tail.then(() => {
103
+ if (failed || ended)
104
+ throw new InsightTransportError('Persistent CLI connection was lost before dispatch.', false);
105
+ const id = ++sequence;
106
+ return new Promise((resolve, reject) => {
107
+ pending.set(id, { resolve, reject });
108
+ try {
109
+ child.stdin.write(JSON.stringify({ jsonrpc: '2.0', id, method: 'cli.execute', params: { argv: args } }) + '\n');
110
+ }
111
+ catch {
112
+ fail('Persistent CLI input was lost; inspect request/status before retrying a changing command.');
113
+ }
114
+ });
115
+ });
116
+ tail = request.catch(() => { });
117
+ return request;
118
+ },
119
+ close() {
120
+ accepting = false;
121
+ return closePromise ??= tail.then(async () => { if (!failed && !ended)
122
+ child.stdin.end(); await exited; });
123
+ }
124
+ };
125
+ }