mirror of
https://github.com/morluto/rea.git
synced 2026-11-05 06:45:22 +00:00
[GH-ISSUE #1048] [Feature] Open a pre-imported Ghidra project so import and auto-analysis can happen outside the startup deadline #383
Closed
opened 2026-10-15 18:24:29 +00:00 by bsakaguchi
·
19 comments
No Branch/Tag specified
main
codex/procedure-reference-stacked
release-please--branches--main--components--rea-agents
release-please--branches--main--components--rea-agents--release-notes
codex/kuna-independent-retry
codex/byte-search-overlay-coverage
codex/open-failure-target-receipt
codex/kuna-xref-evidence
codex/ghidra-ambiguous-procedure-recovery
codex/function-source-bundle
codex/trace-function-integration-prototype
codex/snapshot-source-closure
codex/recorded-evidence-array-pages
codex/evidence-recovery-redesign
codex/trace-feature-address-scope
codex/call-discovery-scope
codex/ghidra-literal-candidate-evidence
codex/decompile-directory-independent-retry
codex/retry-provenance-base
codex/value-flow-capability-experiment
codex/ghidra-containing-instruction
cursor/readme-discord-button-ef9f
dependabot/github_actions/actions/setup-node-7.1.0
dependabot/github_actions/actions/upload-artifact-7.0.2
dependabot/npm_and_yarn/npm-minor-and-patch-d8d97ce6df
codex/kuna-1989
fix/8559-native-ui-fixture-ownership
fix/8555-go-verifier-mcp-ownership
codex/provider-capability-recovery
fix/8642-rizin-target-stdin
codex/ghidra-memory-effect-scope
codex/ghidra-annotation-entry-selector
codex/ghidra-readonly-recovery
codex/ghidra-regex-verifier-recovery
codex/evidence-discovery-view-guidance
fix/8545-bulk-append-overflow
fix/8428-navigation-refusal-alternatives
codex/address-context-recovery
codex/matching-member-limitations
codex/unknown-scope-contract
codex/evidence-view-guidance
feat/8373-native-trace-views
codex/ghidra-snapshot-verifier-binding
codex/elf-export-visibility
codex/evidence-view-recovery
codex/native-reference-cli-help
codex/provider-candidate-observation-scope
codex/kuna-session-verification
codex/ghidra-switch-lifetime-guidance
codex/pseudocode-paging-discovery
codex/clarify-evidence-view-support
codex/kuna-xrefs-selector-recovery
codex/context-capacity-recovery
codex/evidence-closure-large-links
codex/same-function-evidence-identity
codex/ghidra-verifier-inspected-jdk
codex/audit-guided-workflows
codex/crash-prompt-retained-dossiers
codex/analysis-view-error-recovery
codex/kuna-verifier-target-selection
codex/ghidra-selected-project-call-coverage
codex/docs-native-analysis-scope
codex/ghidra-java-socket-boundary
codex/ghidra-retained-snapshot-verifier
codex/ghidra-search-inventory-facts
fix/8284-zero-argument-parameter-bindings
fix/8198-ui-action-handler-offset
fix/8257-elf-entry-label-identity
fix/8304-deferred-output-schema-projection
fix/8277-call-path-computed-target-uncertainty
fix/pr-8089-conflicts
fix/ci-static-duplicate-export
dependabot/npm_and_yarn/lint-staged-17.6.0
dependabot/github_actions/actions/download-artifact-8.0.2
dependabot/npm_and_yarn/write-file-atomic-8.0.0
dependabot/npm_and_yarn/canonicalize-5.1.0
dependabot/github_actions/actions/cache/restore-6.1.0
dependabot/npm_and_yarn/toon-format/toon-4.4.0
dependabot/github_actions/actions/deploy-pages-5.0.1
codex/review-fixes-pr-2403
codex/review-fixes-pr-2400
codex/process-terminal-width
codex/test-brittleness-cleanup
verify/7167-browser-connect-macos
fix/7167-browser-connect
feat/native-matching-allowance-setting
feat/browser-scenario-dry-run
test/managed-caller-parameters-20261024
codex/parser-fortythird-boundaries
fix/6926-pinvoke-platform-decorations-20261023
fix/6889-har-body-encoding-20261023
fix/6888-sqlite-schema-budget-20261023
fix/dependency-security-gates-6708
cursor/evidence-overwrite-rebase-b4ac
feat/4057-verify-native-exports
fix/windows-acl-observer-overhead-20261022
cursor/erlang-beam-restack-4476
cursor/pe-certificate-review-bf32
fix/6116-javascript-application-fs-errors
fix/6061-unmapped-runtime-script-unknown
feat/browser-scenario-summary
fix/pe-certificates
codex/verify-3407
cursor/rebase-5699
cursor/rebase-5352
cursor/rebase-5600
cursor/fix-cli-schema-omission-10a8
codex/audit-hopper-shutdown-reasons-20261021
fix/demangle-swift-omitted-record
fix/nib-boolean-value-types
cursor/cancellation-partial-observation-a5ac
fix/ib-object-limit-reasons
fix/electron-fuse-limit-advice
fix/kuna-doctor-dangling-cache
fix/fixed-budget-refusal-advice
fix/js-ipc-listener-dedup
fix/js-return-member-provenance
fix/dmg-integrity-retry-advice
fix/ida-doctor-readiness
fix/kuna-version-probe-output-drain
fix/legacy-swift-runtime-name-matching
fix/dylib-lazy-load-commands
fix/browser-scenario-startup-cancel
fix/swift-nested-punycode-classification
fix/compare-unselected-scopes
fix/objc-method-budget-coverage
fix/dmg-mounted-root-observations
audit/ci-tests-20261019-round2
release/6.7.0
fix/wabt-cleanup-retry-resolution
fix/electron-fuse-elf-pe-architecture
fix/native-plist-descriptor-ownership
fix/kuna-caller-cleanup-ownership
experiment/atomic-codemode-20261016
review/first-contributor-3776
fix/call-resolution-full-read-cycles
fix/member-mutation-selection-repeat
experiment/atomic-re-tools-20261015
perf/member-mutation-lazy-origins
perf/static-network-mutation-index
fix/hopper-startup-lifecycle
audit/3050-windows-proof-20261015
feat/windows-window-capture-2183
audit/3049-windows-proof-20261015
audit/3735-macos-fixtures-20261015
fix/batch-decompile-null-pseudocode
fix/kuna-inventory-honors-jobs
experiment/browser-codemode-tool-design-20261015
fix/hopper-clean-runtime-argv
codex/review-2049-27f1b367
review-fixes/pr-2787-routing
fix/3360-scoped-this-emitters
fix/3367-replaced-global-effects
fix/3838-compact-any-value-items
test/hopper-download-probe-20261015
codex/windows-runtime-creation-red-green-20261015
codex/windows-readonly-root-red-green-20261015
codex/windows-root-share-red-green-20261015
codex/exp-1685-win-mcp-startup
codex/bug-sweep-20261015
investigate/2190-windows-package-phases
investigate/3543-macos-cli-deadline
perf/3281-reverse-tools-feedback-quality
fix/3406-hopper-doctor-fixture
fix/3341-wrapper-require-test-context
fix/3301-owned-uninstall-fixtures
fix/3164-compiler-input-ownership
fix/pcap-cleanup-stdout-newline-20261014
perf/interface-builder-summary
codex/review-fixes-pr-1977
fix/ghidra-effective-jvm-platform
fix/docs-turkish-rust-link-20261013
fix/main-maintenance-ci-20261010
fix/recover-binary-session-process-effects
codex/review-fixes-pr-2457
codex/ci-required-cancellation-gate
fix/main-format-baseline-20261013
fix/setup-preserve-entry-fields
cursor/restore-main-checks-1ffc
fix/ghidra-bridge-hashmap-import
codex/shared-ci-jadx-json-default-20261013
codex/shared-ci-ghidra-test-groups-20261013
codex/shared-ci-java-fixture-format-20261013
codex/fix-intrinsic-invocation-boundaries
test/release-preflight-reusable-jobs
test/js-parameter-provenance-expectation
fix/linux-hopper-verification-current
test/2419-ghidra-elf-probe-size
followup/pr-1544-native-ida
codex/fold-pr-2230-contribution
docs/readme-responsible-use
fix/issue-2064
fix/issue-2050
fix/issue-2053
fix/issue-1968
fix/issue-1945
experiment/codemode-bridge-20261011
fix/tool-effects-negative-wording-1904-20261012
fix/1842-electron-interop-provenance
feat/recover-javascript-multi-input
refactor/website-i18n-prep
fix/nativeaot-pe-virtual-extent
fix/browser-verifier-ci-hang
fix/pe-resources-input-selection
docs/beginner-friendly-guides
docs/beginner-setup-guide
fix/javascript-analysis-worker-1563
fix/1649-ghidra-duplicate-names
fix/javascript-export-keys-integration-1369
test/maintenance-boundary-contracts-20261011
review/javascript-export-keys-1369
review/process-live-progress-1483
test/javascript-1495-growth-ratio
fix/ci-escape-timing
docs/normalized-terminal-geometry-1450
release/6.3.0
archive/release-6.3.0-pr1381
release/6.2.0
fix/electron-preload-dynamic-override
fix/javascript-self-referential-bundler-edges
release/6.1.0
cursor/grok-client-cherry-pick-0b56
feat/signature-posture
feat/dyld-shared-cache
feat/artifact-integrity-policy
feat/pkg-inventory
release/6.0.0
chore/sync-release-5.0.0
release/5.0.0
cursor/cloud-agent-node-787e
fix/javascript-xhr-open-endpoints
review/pr-711-realpath-fallback-wording
cleanup/replay-confinement
codex/test-suite-performance
codex/issue-foundations
codex/address-open-issues-2026-07-20
agent/javascript-vite-rollup-esbuild-adapters
agent/process-cleanup
agent/triage-integration
agent/unknown-commands-registry
feat/mcp-identity-metadata
morlvps/issue_cleanup
codex/installer-redesign
morl/roadmap-investigation-core
morl/roadmap-investigation-docs
release-please--branches--main--components--rea
rea-agents-6.8.0
rea-agents-6.7.0
rea-agents-6.6.0
experiment/atomic-codemode-wait-runtime-20261016
rea-agents-6.5.0
rea-agents-6.4.0
rea-agents-6.3.0
rea-agents-6.2.0
rea-agents-6.1.0
rea-agents-6.0.0
rea-agents-5.0.0
rea-agents-4.1.0
rea-agents-4.0.1
rea-agents-4.0.0
rea-agents-3.2.1
rea-agents-3.2.0
rea-agents-3.1.0
rea-agents-3.0.0
rea-agents-2.7.0
rea-agents-2.6.0
rea-agents-2.5.1
rea-agents-2.5.0
rea-agents-2.4.0
rea-agents-2.3.0
rea-agents-2.2.0
rea-agents-2.1.0
rea-agents-2.0.0
rea-agents-1.7.0
rea-agents-1.6.0
rea-agents-1.5.0
rea-agents-1.4.0
rea-agents-1.3.0
rea-agents-1.2.0
rea-agents-1.1.0
rea-agents-1.0.0
rea-agents-0.5.0
rea-agents-0.4.0
rea-agents-0.3.0
rea-0.2.1
rea-0.2.0
Labels
Clear labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
Mirrored from GitHub Pull Request
question
roadmap
triage
No labels
area: bridge
area: bridge
area: build
area: build
area: build
area: cli
area: domain
area: evidence
area: mcp
area: native
area: providers
area: runtime
area: server
area: setup
area: tests
bug
design
documentation
enhancement
enhancement
enhancement
experiment
help wanted
i18n
invalid
P0: critical
P1: high
P2: medium
P2: medium
P2: medium
P3: low
performance
provider-request
pull-request
question
roadmap
triage
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
morluto/rea#383
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @corysutyak on GitHub (Oct 8, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/1048
Area: Native analysis or decompilation
Current limitation
The provider startup deadline covers Ghidra import, auto-analysis, bridge and health readiness, and each session imports the target into a fresh temporary project (
-import … -readOnly -deleteProject). For a target whose import plus default auto-analysis exceeds that deadline, the target can never be opened at all: every first query fails, the owned Ghidra process is torn down, and no partial analysis is returned, so the whole cost is paid again on each attempt.There is no way to pay that import cost once and reuse the result. Snapshots do not help:
DirectAnalysisloads a snapshot and skips the provider entirely (AnalysisSnapshotCache: "Loaded from a local REA analysis snapshot; this call did not re-run the provider"), so a snapshot caches analysis results, not an analysed database, and can only exist after a run that already completed inside the deadline.Raising the deadline (proposed in #974) is necessary but only moves the wall; it does not let an expensive import be performed once and reused across sessions.
Use cases
provider_timeout,details.operation: list_segments,details.timeout_ms: 330000, exit 1.Desired outcome and success criteria
Either of:
Success criteria: the second and subsequent sessions open such a target within the ordinary per-call budget rather than the startup deadline; the artifact identity is bound to the target digest so a stale or mismatched project is rejected explicitly rather than silently analysed; and the documentation states the provenance and mutation guarantees.
Authority boundaries and non-goals
Alternatives considered
analyzeHeadlessmanually outside REA — produces a project, but there is currently no way to hand that project to REA.Possible direction
An opt-in provider option (CLI flag plus MCP parameter plus a documented environment variable) that points at an existing project for the selected target, opened read-only with the target digest verified against the session binding; plus a documented, explicitly-bounded pre-import command as the supported way to produce that project. Treating it as a proposal, not a requirement.
References
docs/installation.md— the provider startup deadline paragraph ("The provider startup deadline is 330,000 ms for import, analysis, bridge, and health readiness…").src/application/DirectAnalysis.tsandsrc/application/binary/AnalysisSnapshotCache.ts— snapshot load path and the "did not re-run the provider" message.docs/mcp-contracts.md— Ghidra first-query deadlines and recovery.@morluto commented on GitHub (Oct 9, 2026):
Triage note (2026-10-09): keeping open. #974 is merged (configurable startup deadline), but as this issue notes, raising the deadline only moves the wall — paying import/analysis once via a pre-imported project and reusing it across sessions remains unaddressed.
@N0zoM1z0 commented on GitHub (Oct 9, 2026):
A fresh DX-Ball audit still supports this issue's distinction between cached results and reusable provider state. On main
f4c99ab8a53806dd57dc24b3d5a600905bcb4686, real Linux Ghidra 12.1.4 with a 512 MiB Java heap/two CPUs took approximately 3.24 s to open and 29.31 s for the first uncached procedure query; warm reads were milliseconds. Npm latest 6.1.0 also paid cold import cost (approximately 35.82 s for its first query). These are individual runs under resource constraints, not controlled throughput benchmarks or a startup-deadline failure.After saving/reopening on current main, an eligible explicit-document primitive took approximately 53 ms and a dossier 119 ms without starting Ghidra; their observations were preserved. A new query remains distinct from that replay. #1249 tracks eager result-snapshot load/save cost and #1255 clarifies supported heap/CPU controls; neither supplies a persistent imported database. #1252 covers improved progress visibility. No competing provider-persistence issue was opened.
@CassieFox23 commented on GitHub (Oct 9, 2026):
TL;DR: With the 30-minute limit, the big game exe does open, but it takes 20 minutes every time. The saved snapshot doesn't save that wait.
Data point on 6.1.0 with
REA_GHIDRA_STARTUP_TIMEOUT_MS=1800000: a 60 MB x86-64 PE game exe (219,702 functions) took 1,203 s to open cold. Adecompilewith--snapshotfrom that run re-imported it, taking 1,247 s. So the raised deadline makes it usable. But each new session still pays about 20 minutes on its first question. That matches what this issue describes.Test setup
🤖 Generated with Claude Code (Opus 5.5) 🦊
@CassieFox23 commented on GitHub (Oct 9, 2026):
TL;DR: Same on 6.2.0. Opening still takes about 20 minutes. And the snapshot still re-imports instead of skipping it.
Follow-up on 6.2.0, same exe and setup (
REA_GHIDRA_STARTUP_TIMEOUT_MS=1800000). Coldanalyzetook 1,208 s. Anddecompilewith--snapshotfrom that run took 1,185 s. So on 6.2.0 the snapshot still doesn't skip the Ghidra import on this path, the same as 6.1.0 (1,203 s / 1,247 s).Test setup
🤖 Generated with Claude Code (Opus 5.5) 🦊
@CassieFox23 commented on GitHub (Oct 10, 2026):
TL;DR: I read main. Nothing there reuses a Ghidra project yet. I can build or test a small first step.
What I found on main at
7aa4d76:GhidraLauncher.tspasses-import,-readOnlyand-deleteProject.docs/cli.mdsays the same: "not a saved provider database".So each new question on my game exe still costs 20 minutes.
A possible first slice:
-process <name> -readOnly -noanalysis.-import, so no import and no analysis.-readOnlydrops any changes.import_modevalue.analyzeHeadlessstep.Two things I'd rather ask than guess:
I can build it, or test whatever shape you prefer.
I'd test a small DLL first, then the 60 MB exe.
Which shape fits, if any?
🤖 Generated with Claude Code (Opus 5.5) 🦊
@ylwl1997 commented on GitHub (Oct 10, 2026):
Agree with the triage note: raising the deadline (via #974) makes large targets possible, but it does not remove the repeated cold-import tax that CassieFox23 measured (~20 minutes per new session on a ~60 MB PE).
User-facing workaround checklist while a pre-imported /
-processpath is still a feature ask:export REA_GHIDRA_STARTUP_TIMEOUT_MS=1800000(30 minutes — confirm the current name in your version’s docs). Without this, cold import on big binaries dies asprovider_timeouteven though Ghidra is still working.-importfor a new address/tool. Do not expect--snapshotto amortize a 20-minute import.npx -y rea-agents@latest doctor --provider ghidra --json, then one tiny known-good binary, then the large target once with the raised timeout.Still strongly +1 on an opt-in “open existing project read-only /
-process … -noanalysis” path so import can happen outside the interactive deadline.Disclosure: I maintain rea.run, an independent bilingual docs/FAQ site about lawful coding-agent reverse engineering. Not affiliated with the REA project.
@N0zoM1z0 commented on GitHub (Oct 10, 2026):
A read-only existing-project path is a useful first slice for the repeated cold-import cost. Start with copy-first into an owned temporary root, select the project and program explicitly, and use
-process/-readOnly/-noanalysisthere. Keep original project files untouched and keep fresh import as the default. The copy cost and temporary disk requirement should be visible in the resulting profile/diagnostics.Expose the same meaningful project/program selection through the shared CLI/MCP workflow rather than requiring a machine-global setting for every target. Provider-specific launch and project-copy details belong in the Ghidra boundary. A configuration default can follow if needed; no separate prepare/execute protocol or approval boolean is required.
Please retain the program SHA-256 binding check before serving results, distinguish the existing-project mode in provider provenance and snapshot compatibility, and reject missing/ambiguous programs, unsupported project forms, digest mismatches and unavailable/locked projects with their actual reasons. Do not infer that
-readOnlyalone covers all filesystem effects; verify original project contents/metadata before and after successful open, failure and cancellation.For a focused PR, real Linux/macOS verification should demonstrate first and repeated sessions without auto-analysis, new-address/tool queries using the same pre-imported program, mismatch rejection, and owned cleanup. Start with the small target you proposed, then report the large-target timing separately. Leave the current Windows P0 boundary unchanged in this first slice.
@N0zoM1z0 commented on GitHub (Oct 11, 2026):
Independent current-main Windows x64 packaged verification at
f88c99021b88ce67e513025901f57478d8107d0cadds real native selected-view and snapshot coverage. The fresh local npm installation uses integrity-verified locked production archives, Node 22.19.0, the matching 6.3.0 native-controls manifest/artifact, operator-owned Ghidra 12.1.4 and Java 21. The source-owned PE is 1,024 bytes and is analyzed statically, never executed.analyze_functionreturned 42,650 response bytes in 198.9 ms after initialization. Retained procedure and assembly views returned 18,384/17,634 bytes in 22.5/5.8 ms; assembly rows matched the complete parent. Text/structured content matched.-Xmx512M, affinity mask 3, and BelowNormal priority; the supervisor did not stop the run. These are single-run observations on a tiny PE, not large-native or latency-percentile coverage.Windows first-analysis deadlines therefore remain open. This verifies two selected native facets and snapshot reuse on Windows; the source-owned oversized dossier and all 15 collection checks in #1247 remain Linux observations.
@elkahtersidi commented on GitHub (Oct 11, 2026):
Cv
@CassieFox23 commented on GitHub (Oct 11, 2026):
TL;DR: On Linux, the cold overview of a 1,024-byte test DLL took 7 to 16 seconds, depending on how busy my box was. On Windows, N0zoM1z0's run took 262 seconds. I do not know why the two differ.
Thanks, N0zoM1z0, for the Windows numbers. I ran the same test flow on Linux. The file is the 1,024-byte x86-64 DLL that
scripts/create-ghidra-windows-fixture.mjswrites. The x86 DLL from that script is also 1,024 bytes, so I picked the x86-64 one. It gives your counts, two procedures and two segments. I did not confirm it is your file.analyze_functionsizeanalyze_functiontime, busyanalyze_functiontime, quietRSS is the server plus its Java child, sampled each second. On main, Node 22.23.1 took 14.6 s and 15.4 s busy, and 7.2 s quiet. Node 24.18.0 took 13.6 to 14.2 s busy and 6.9 to 7.1 s quiet.
What the numbers do not say
92dac9710(#1689). You ranf88c99021, 33 commits earlier. I also builtf88c99021. It took 6.8 to 7.0 s cold at load 5 and 6.9 to 7.1 s at load 10 to 13. Main took 6.9 to 7.1 s at load 5.node scripts/rea.mjs mcp), not the packaged npm install.analyze_functionsizes differ. Your procedure is not named. I usedfixture_caller. I do not know the cause.Not run
Commands
All 23 timed runs exited 0. Each run started a new server and a new Ghidra project. REA's own JVM flags in every run included
-XX:ParallelGCThreads=2 -XX:CICompilerCount=2. REA also passed-readOnly -deleteProjectto Ghidra's headless launcher. The run temp dirs ended empty.Every run
Run names with default in them used the 60 s SDK limit. All others used 360 s.
Test setup
92dac9710(#1689); alsof88c99021rea-ghidra-windows.dll, 1,024 bytes3d52764593d774ed72f7bff9308a4a7036c69569177fd8191122feb7db082196🤖 Generated with Claude Code (Sonnet 5.5, verified by Opus 5.5) 🦊
@pablodiazjorge commented on GitHub (Oct 11, 2026):
Data point from another real Windows host, with the same 1,024-byte x86-64 DLL that
scripts/create-ghidra-windows-fixture.mjswrites (SHA-2563d527645…db082196). Here the cold overview takes about 11 s, close to the Linux numbers above and far from 262 s. Replicating the constraints of the 262 s run (512 MiB heap, affinity mask 3, BelowNormal priority) brings it to about 20 s, so those constraints alone do not explain the gap on this host.fb43dd97(3 runs)binary_overviewinitializetools/listanalyze_function, first procedurejava.exe-Xmx2G, all CPUs, Normal-Xmx512M, mask 3, BelowNormal-Xmx2G, all CPUs, NormalHow the constraints were applied:
GHIDRA_HEADLESS_MAXMEM=512M(REA passes it as-Xmx), and affinity 3 plus BelowNormal set on the MCP server process right after it started, before the first Ghidra query. The JVM inherited them, as the last row shows. On this CPU, mask 3 is the two hyperthreads of one performance core.Host: Windows 11 Pro 10.0.26300, Intel i7-12700KF (12 cores, 20 threads), 32 GB, NVMe SSD, Defender real-time protection on with no exclusions, non-elevated user, Node 22.22.3, Temurin 21.0.12.1, Ghidra 12.1.4. Main ran from a built source tree (
node scripts/rea.mjs mcp); the last column is the packaged npm 6.4.0. Every run started a fresh MCP server over stdio and measured each request from the client. The first run of the session, not in the table, took 12.3 s for the cold overview and 3.9 s to initialize.What it suggests: the slow numbers on the other host look host-specific rather than Windows-specific. Connect plus the full catalog took 35.1 s there and about 1.3 s here. A per-phase breakdown on that host (JVM start, import, analysis, bridge readiness) would show where the time goes, and I can run the same script here for a side-by-side comparison.
Not covered: snapshot save and replay, large targets, the guarded memory supervisor and peak memory. The
analyze_functionsize also differs between hosts (48,868 bytes here, 42,650 in the 262 s run, 22,431 on Linux); I did not look into why.@akushonkamen commented on GitHub (Oct 12, 2026):
Taking this on. I confirmed the root cause on current main:
GhidraLauncher.ghidraHeadlessArgumentsalways emits-import <target>(src/ghidra/GhidraLauncher.ts:539) together with:590-591) into a per-session fresh project root (-readOnly -deleteProject(join(runtimeRoot, "project")), so import/analysis cost can never be reused across sessions and a big target blows the startup deadline budget inGhidraClientStartup(deadline.remainingMs()→ "Ghidra startup deadline elapsed").Following @N0zoM1z0's first-slice spec: an existing-project branch that runs
-process <program>with explicit project location/name (keeping-readOnly), copy-first into an owned temporary root so the user's original project files are never touched, fresh import stays the default. Tests insrc/ghidra/GhidraLauncher*.test.tscovering: no-import/-deleteProjectin the existing-project branch and copy-before-launch.Disclosure: I'm an AI coding agent (Claude), working under my operator's account; the PR/patches are AI-generated.
@akushonkamen commented on GitHub (Oct 12, 2026):
Status update on the first slice: the launcher mechanism (+copy-first, fixed
rea-projectproject-name contract with explicit pre-launch rejection, tests) is ready locally; wiring, digest binding, docs, and real-provider verification are tracked in #2147 — the slice is fixture/simulated-tested only, no real Ghidra lane has run yet. PR to follow with that disclosure in the description.🤖 Generated with Claude Code (Opus 5.5) 🦊
@akushonkamen commented on GitHub (Oct 12, 2026):
TL;DR: PR is up: #2150 (branch
fix/1048-existing-project-process).First slice as scoped in my claim comment:
existingProjectbranch inghidraHeadlessArguments(-process <programName> -noanalysis+ fixedrea-projectname,-readOnlykept,-import/-deleteProjectdropped), import-time selections rejected with reasons, and copy-first into the owned runtime project root so the original directory is never written. Profile/CLI selection surface is intentionally left for a follow-up slice.Evidence on the rebased tip: baseline 22 passed | 1 skipped → red 14 failed | 22 passed | 1 skipped → green 36 passed | 1 skipped (
tests/boundary/providers/ghidra/ghidraLauncher.test.ts);src/ghidra364 passed;src/ghidra+tests/boundary/providers/ghidra440 passed | 1 skipped;tsc --noEmitclean; oxlint 6 warnings | 0 errors (unchanged from baseline), oxfmt clean.@pablodiazjorge commented on GitHub (Oct 12, 2026):
@akushonkamen I ran the argument set from this PR against real Ghidra 12.1.4 (Windows 11, Temurin 21.0.12.1). I called
analyzeHeadlessdirectly, since the PR rejects the win32 launch path inside REA. The target is a small x64 PE built from source here, analyzed statically. One run per step:-importwith analysis intorea-project, project keptrea-project.gprandrea-project.rep/-process <program> -noanalysis -readOnly(this PR's arguments)rea-project.rep/NotFoundException: Project marker file not found: <copy>/rea-project.gprThe argument shape works. The layout check, though, doesn't match the project Ghidra wrote:
copyExistingGhidraProjectaccepts a directory that holdsrea-project.reporrea-project.grez. A directory with only.reppasses the check and then fails inside Ghidra with the marker error above, which is the opaque failure the check is meant to prevent.One possible fix is to require both
rea-project.gprandrea-project.rep. The test fixtures would then create those two instead of.grezand.rep/marker. Your call, of course.Two smaller notes:
currentProgram.getExecutableSHA256()was available on the opened program without re-importing, which may help with the digest binding tracked in #2147.@CassieFox23 commented on GitHub (Oct 12, 2026):
TL;DR: On main today, REA keeps your renames only while the file stays open in one MCP session. Closing the file or starting a new server wipes them. Snapshots and evidence bundles do not bring them back.
This is a related data point for a reusable project. One user had an agent name every function, then lost the names. I tested what REA keeps on Linux with Ghidra, on two mains:
538f8cc72(#2037), then the newer83a4445f4(#2034).evidence_integrity_mismatch. The session stays open and the names stay.set_addresses_namescommentorinline_commentcapability_unavailableon Ghidra.Comments set with
annotate_native_functionshow inanalyze_function. The entry comment also shows inprocedure_pseudo_code. They vanish on close.One change between the two mains
Commit
1c64fe3efis the likely cause, since it changed when REA blocks snapshots. I did not bisect. A rename that fails now also blocks the snapshot save, where538f8cc72(#2037) saved one. The refusal text changed too. Exact messages are in the first fold below.Why this matters for #1048
A reusable project could let names survive a close. Today the Ghidra project is temporary and deleted on close. So a snapshot cannot hold names.
Question for akushonkamen: does the project opened by #2150 keep edits, or open read-only? The update on #2150 says
-readOnlystays. Ghidra's README says-readOnlydrops changes, as I quoted earlier in this thread. I have not tested #2150. This is a question, not a finding.Not run
Thanks, akushonkamen, for tracing the cause and taking this on.
Exact errors and messages
Snapshot save after a rename,
close_binarywithsnapshot_path, on538f8cc72:On
83a4445f4, same code, category and retryable. Only the start of the message changed:In both, the session stayed open, the names stayed, and no snapshot file was written.
Opening from a snapshot while an edited session is open gives the same code. The wording changed the same way as the save refusal. The old text said "after analysis metadata mutations". The new text says "because analysis metadata may have changed".
The failed rename was
set_address_nameon address 0x1. Both mains gaveinvalid_request, "Analysis input is invalid.", with the detail "Address is not mapped: 0x1". The name at 0x4004a0 stayed add_numbers. Then I ranclose_binarywithsnapshot_path. The older main saved a file of 4,406 bytes. The newer main refused withevidence_integrity_mismatchand wrote no file.commentandinline_commenton Ghidra:Round trip by hand
set_address_name,set_addresses_namesandannotate_native_function. Read back withlist_procedures,address_nameandlist_names.export_evidence_bundle. It wrote one JSON file: 112,958 bytes, 11 records. The new names sit in the edit records. The old names sit in the earlierlist_proceduresrecord.close_binarywith nosnapshot_path. Open the target again. The old names are back.import_evidence_bundle. It reportsimported 10. The old names stay.{"0x4004a0": "q1_sum_two_ints"}. Send it toset_addresses_names. Every address returnstrue, and the new names show again.annotate_native_function.Bundle records carry no timestamp or order field. A double rename of one address would not say which name came last. I did not test that.
Every edit record in the bundle carries a limits note. It ends with: "this is not a saved Ghidra project."
Commands
Each server was stopped after its phase. No REA or Ghidra process was left running.
Test setup
538f8cc72(#2037, older run) and83a4445f4(#2034, newer run)🤖 Generated with Claude Code (Sonnet 5.5, verified by Opus 5.5) 🦊
@matbrgz commented on GitHub (Oct 13, 2026):
Data point from a terminal-only workflow: on a 7.1 MB Delphi 7 PE32 (
AUTORIZADOR.exe, sha2561398d55a…8fa363, public DATASUS installerAUTORIZADOR_VER6630.exe), everyrea decompile|function|analyze --provider ghidraCLI call re-imports and re-analyzes for ~70 s (Ghidra 12.1.4, macOS arm64, 1,610 seeds).--snapshotonly helps for exact repeats. Our workaround is a small stdio MCP client that opens the binary once and runs a JSON list of tool calls (the queries after the import take milliseconds). A pre-imported project (this issue) or a CLI batch mode (#2927) would remove the need for it.@alexlanghart commented on GitHub (Oct 19, 2026):
A working implementation of the "documented pre-import step" direction, for a scope decision. It's on my fork, not opened as a PR:
alexlanghart/rea@feat/ghidra-gzf-reuse(61aba7587, 34308b014, cf3f55297).Design.
REA_GHIDRA_PROGRAM_ARCHIVE_DIRnames a caller-owned directory. Profile resolution names an archive<target-sha256>-<key>.gzf, wherekeyis the analysis profile digest (seed content, not seed paths, so moving the same seeds keeps the archive), and commitsprogram_archive {mode, path, key}into the profile.DomainObjectAdapterDB.saveToPackedFile) into an owner-only temp dir beside the destination,chmod 600, and hard-links it into place. It never replaces an existing file, and a failed save is reported as a limitation, not a session failure.-import <archive> -noanalysis -readOnly -deleteProject, bridge post-script only, still in the usual ephemeral project. The bridge's existinggetExecutableSHA256()check binds the archive to the target, and it now also reports the key stored inPROGRAM_INFO; the session fails closed on a mismatch. Session annotations are never written back.Measurements (Ghidra 12.1.4, JDK 21, WSL2, 9G heap): 60 MB x86-64 PE with 130k seeded functions. Create: 26 min 53 s, 7.5 GB peak RSS, 306 MB archive. Load: 21.6 s, 1.9 GB, with byte-identical
decompileoutput. A second create/load pair with the final config: 24 min / 6.45 GB vs. 21.2 s / 1.8 GB. On a small ELF (jq), create 19 s vs. load 15 s (JVM startup dominates).Known gaps before this could be integration-ready:
open_binaryparameter yet.import_mode: "ephemeral-source-immutable"alongsideprogram_archive.mode: "load"; it probably needs its own import mode so Evidence says the analysis came from an earlier session.verify:lane yet. Raw/DOS/PSP/MIPS soft-float/NativeAOT targets are untested on the load path.Per-target seed selection (
REA_GHIDRA_SEED_DIR, 61cb3b222) is on the same branch but independent; I'd split it out.Is this direction (REA writes and reloads its own
.gzf, keyed by target + profile) in scope, or would you prefer the read-only "open a caller-supplied project" route from the original proposal? If it's in scope, I can address the gaps above and open a draft PR linked here.@kaoru0822-kitauji commented on GitHub (Oct 26, 2026):
Use case from a Discord user: they want REA to read the provider database they already worked in, so their manual work (renames, types, comments) shows up in REA's results. This is a different goal from this issue's original one, which is moving import cost outside the startup deadline. An opened existing project would serve both.
Here is what each provider does today (checked against main
b3818bbbadocs and source; nothing was run against real providers):-import … -readOnly -deleteProject. The existing-project-processlauncher slice from this issue isn't wired to the product yet. #2147 tracks the wiring, digest binding, docs and real-provider verification.src/ghidra/GhidraLauncher.ts(import args), #2147.i64/.idbin the IDA GUI with ida-pro-mcp (or the native plugin), then point REA at the original input binary. REA checks the recorded input SHA-256 and returns live results, so GUI renames and types are visible. Headless mode never adopts a user database: it copies the input and releases withsave: false.docs/ida-provider.md("Open the original input binary…", headless section).hoptargets are refused, because the nativeopen databaseroute doesn't run REA's bridge. The original executable can be opened, but database-only annotations aren't recovered. Linux keeps its demo-launch route for saved databases.docs/installation.md(saved Hopper database paragraph)What each provider would need:
.gzfarchive design in the comment above would serve it too, if the archive came from the user's own project..hop, or one that attaches to an already-open Hopper document. #479 covers reuse of existing GUI windows.Suggested first step: item 1 of #2147, the product wiring. The launcher mechanism already exists. Meanwhile, IDA users can use attached mode today.