Files
rea/docs/cli.md
T
Muhammad Hamza 169512a35b feat(cli): report version and runtime with an explicit output format (#6530)
* feat(cli): report version and runtime with an explicit output format

`rea --version --json` and `--version --format <format>` ignored the format
and printed only the bare version, so support reports gathered the runtime
and platform by hand.

A root --version request that selects a format now renders a documented
report: package name and version, JavaScript runtime and version, platform,
architecture, and whether the runtime satisfies the supported range. It
contains no paths, environment values, user or host names, and starts no
provider. Plain --version is unchanged, --help keeps precedence, and other
output controls keep Incur's plain version.

The runtime verdict uses a new shared supportsJavaScriptRuntime rule that
rea doctor now uses too, so both judge Bun by its Node.js compatibility
version. mcp doctor's private JSON/format renderer moves to cliOutput as
renderCliDocument and is shared with the version report.

Closes #5483

* refactor(errors): centralize input failure construction

Carry caller messages through the existing schema issue owner instead of constructing and discarding an intermediate input error. Remove forwarding schema helpers and migrate equivalent constructors across investigation, firmware, dylib, process, and screenshot workflows while preserving diagnostic paths and causes.

* docs(readme): add Roman Urdu edition (#6499)

* docs(readme): add Roman Urdu edition

Register ur-Latn with a pending website catalog and preserve English command examples.

Script-tag handling follows morluto's shared helper proposed in PR #2043 (c46f606c89).

* test(website): cover completed script-tag page metadata

* fix(process): parse native teardown relation sentinels

* fix(cli): make version report privacy checks environment-independent

The CLI test rejected any report containing the OS account name, so an
account named node, linux or rea failed a correct report. Check unique
caller-controlled HOME, cwd and environment markers instead; the strict
schema still rejects any additional field.

The CLI guide said --version with other output controls prints the plain
version, but invalid combinations such as --json with --token-limit report
their existing output-flag error first. Describe both outcomes and test them.

* refactor(nativeaot): share report facts across budget stages

Centralize parse-wide identity and coverage facts while keeping conservative admission values separate from measured rows and counters. Reuse the derived truncation reason and retain the final serialization bound.

Tighten the report-budget regression so unexpected parser finalization errors cannot be swallowed by its budget search.

* fix(adb): preserve empty properties and verbatim version names

* fix(artifacts): recognize empty Zip64 containers

Fixes #6540

* fix(erlang): accept uninterpreted BEAM alignment bytes

Fixes #6517

* fix(gpu): accept PTX entries without parameter lists

Fixes #6493

* fix(python): preserve signed code-object line numbers

Fixes #6490

* refactor(ghidra): centralize load image check recording

Share expected and observed check construction across MZ, COM, and raw-binary attestations. Preserve format-specific rules and source coordinates, and derive mapping callback types from the recording owner.

* fix(inspector): preserve script identity and parse-failure facts

Fixes #6535

Fixes #6546

* fix(artifacts): recover malformed PYZ sizes without losing siblings

Fixes #6120

* fix(erlang): accept extended BEAM atom lengths

Fixes #6503

* refactor(erlang): reject overflowing BEAM atom lengths

* fix(gpu): preserve PTX and AMD target facts

Fixes #6469

Fixes #6483

* refactor(targets): preserve ambiguous MZ header evidence

* fix(adb): retain refused activity launch reports

Parse complete nonzero Activity Manager reports while preserving other command failures and their captured output. Admit dollar signs only in the activity component name for nested Android classes.

Fixes #6528

Fixes #6527

* fix(mcp): retain partial evidence through shared delivery

* fix(python): honor version-specific code equality

Fixes #6547

* fix(pyinstaller): preserve namespace declarations

Project PYZ namespace packages as metadata so their query paths do not claim output directories. This lets independent CArchive files retain the same logical path and remain inspectable and extractable.

Fixes #6539

* docs: clarify evidence ownership and verification guidance

* docs(adb): clarify emulator observation field

* docs(artifacts): clarify active-reader extraction scope

* fix(erlang): select the last repeated BEAM chunk

Fixes #6518

* fix(il2cpp): distinguish rank-one array types

Fixes #6534

* fix(python): align pyc and PYZ marshal decoding

Fixes #6560
Fixes #6559

* fix(browser): preserve frame identity across captures (#4040)

* fix(browser): preserve capture evidence fidelity

* fix(browser): align frame identity comparisons

* fix(browser): retain historical frame evidence

* fix(electron): retain same-document script owners

* fix(electron): bind frame proof to tree reads

* fix(browser): retain malformed frame scope

* fix(browser): retain WebMCP event scope

* fix(browser): retain malformed timeline identity

* fix(browser): unify frame identity and scope

* fix(electron): prove enclosing frame ancestry

* fix(electron): separate ancestry from file policy

* fix(browser): preserve transient fragment semantics

* fix(browser): retry uncertain initial frame scope

* fix(browser): preserve runtime frame identity

* refactor(browser): separate independent capture fixes

* fix(electron): detect tree-first document replacement

* fix(electron): retain same-document tree authority

---------

Co-authored-by: eco-null <eco-null@users.noreply.github.com>
Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>

* fix(elf): resolve symbol versions from requirements

Fixes #6533

* fix(elf): follow loader version index precedence

VERDEF entries replace VERNEED names for shared indices, matching glibc lookup behavior.

* test(firmware): bind owned producers and exercise real limits

* fix(adb): preserve push target semantics

Fixes #6566

Fixes #6567

* fix(cli): merge sibling output filter slices

Fixes #6542

* fix(browser): preserve Link context semantics

Fixes #6504

Fixes #6505

Fixes #6506

* fix(python): classify historical headers and signed flags

Fixes #6568, #6487

* fix(python): normalize legacy code flags for equality

Preserve CPython 3.7–3.10 constructor flag semantics in code keys.

* fix(environment): compare captured bodies by representation

Keep JSON, text, and retained bytes distinct through fidelity comparison. Compare binary bodies by bytes, including valid UTF-8 bytes against equivalent text, and keep empty-body compatibility explicit.

Fixes #6564

* docs: clarify derived values and comparison controls

* fix(environment): scope fidelity ID normalization

Reserve equal global ID pairs and stop normalizing contested pairings. Keep numeric measurements literal, scope keyed collection identities through learning and comparison, and normalize string references only where learning established the same field as an ID.

Fixes #6565
Fixes #6550
Fixes #6557

* test(process): print the progress frames when the sparse-child bound fails (#6427)

The sparse-child capture test asserted the frame bound with a bare boolean,
so a failure only printed "expected false to be true". The assertion now
carries the running progress details (elapsed time, frames, samples,
interactions) as its failure message. This only adds diagnostics to a
failure; it does not change what passes and does not fix the flake.

Refs #5889.

🤖 Generated with Claude Code (Sonnet 5.5) 🦊

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(il2cpp): name the metadata file when linking finds malformed metadata (#6425)

* fix(flutter): honor ELF note alignment when reading build IDs (#6423)

* fix(flutter): honor ELF note alignment when reading build IDs

* test(flutter): key shared note ranges by effective alignment

Cover a program and section declaration that share one note range: differing effective alignments (8 and 4) must both be read, while declarations that both normalize to four bytes (1 and 4) still share one read. 24-byte build IDs pad identically at both alignments, so only the range key decides the read count.

* refactor(firmware): centralize audited tool requirements

* fix(javascript): associate requested bindings only with resolved native addons (#6402)

* fix(javascript): associate requested bindings only with resolved native addons

* test(javascript): cover the exact native addon association

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>

* fix(python): reject code keys and set members with unhashable consts (#6424)

* fix(python): reject code keys and set members with unhashable consts

* fix(python): refuse to hash a tuple that is still being read

* fix(python): hash a code object's co_consts tuple, not its item list

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>

* fix(model): recognize named chat templates in summaries

Count retained template content rather than only the default key; keep names-only inventories distinct.

Fixes #6569

* fix(model): retain resolved GGUF alignment under cancellation

Publish alignment from the parser when explicit metadata validates it, or when metadata completion establishes the default. Preserve that fact through later parsing and hashing failures.

Fixes #6579

* fix(environment): reject out-of-range clock offsets

Reject invalid ISO offsets while preserving valid boundary values. Validate stored clock-format offsets through the same parser so malformed imported formats cannot reach rendering.

Fixes #6524

* fix(environment): preserve submillisecond insert ordering

Compare retained submillisecond components after milliseconds, so ordered collections recognize and place distinct timestamps correctly.

Fixes #6525

* fix(environment): restrict epoch normalization to clock fields

Require a time-field token boundary before treating numeric values as epoch clocks, so identifiers such as media format codes remain literal. Clarify recognized field forms and clock offset and precision semantics in the fidelity guide.

Fixes #6551

* fix(process): preserve sibling path identities

Keep aliases on selected paths at clear text delimiters so a longer sibling filename is not rewritten as the executable. Version the normalization contract and cover source and actual PTY behavior.

Fixes #6586

* fix(sigrok): retain recording suffix for autodetection

Copy recordings under a private filename that retains the caller-selected final suffix, and pass that filename to sigrok. This restores filename-based autodetection without exposing the source directory.

Fixes #6580

* test(go): assert unresolved MZ candidate boundary

* fix(pe): ignore unused export ordinal slots

Fixes #6577

* fix(macho): recognize arm64_32 binaries

Fixes #6581

* fix(go): honor amd64p32 pointer width

Fixes #6590

* fix(pe): accept BER indefinite CMS values

Fixes #6574

* fix(browser): reject overlapping indexed source maps

Fixes #6562

* fix(browser): resolve prefixed XHTML form actions

Fixes #6561

* fix(browser): preserve well-known path case

Fixes #6571

* docs(browser): clarify parser evidence contracts

* fix(gpu): accept percent-prefixed PTX entry names

Fixes #6592

* fix(gpu): accept PTX compute target aliases

Preserve the source spelling of NVIDIA's documented compute_xx target synonym.

Fixes #6494

* fix(gpu): parse legacy PTX body parameters

PTX 1.0 through 1.3 declares kernel parameters inside the entry body. Keep later-version parameter-list parsing unchanged.

Fixes #6594

* fix(gpu): keep unknown targets out of exact filters

Fixes #6599

* fix(gpu): resolve extended CUBIN symbol sections

Fixes #6600

* docs(firmware): document the Windows Unblob submodule checkout (#6464)

On Windows, the pinned Unblob commit cannot be checked out because 11
upstream fixture paths under tests/integration/ are invalid on NTFS.
Document the verified sparse-checkout workaround and point Windows
contributors to it from CONTRIBUTING.


Claude-Session: https://claude.ai/code/session_01LjhoPGpqAwHwcCgectzRsp

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(recovery): retain file outcomes and cleanup ownership

Use shared owned-file and directory primitives throughout Wakaru discovery,
snapshots, report parsing and publication. Preserve primary read failures and
completed fingerprints when final close fails or receives cancellation.

Retain exact cleanup capabilities before retiring workspaces, block new work
while cleanup is unresolved, and bind error status to the aggregate owner so
partial cleanup and later retry keep resource attribution current.

* fix(pe): preserve biased export ordinals

Accept the format-derived ordinal range for PE export slots.

* docs: clarify parser authority and compatibility evidence

* fix(python): preserve code-name identity

Fixes #6593

* fix(managed): validate metadata operands and locals declarations

Classify MemberRef operands from parsed signatures, validate signature table references and LocalVarSig blobs, and compare observed locals declaration presence. Keep partial CIL facts and transient-budget ownership at the method reader.

Fixes #6578
Fixes #6572
Fixes #6558
Fixes #6513

* fix(python): preserve historical signed code fields

Keep signed co_stacksize and co_flags for historical magic entries whose constructors accepted them. Preserve magic 3410 with a constructor-revision limitation; reject negative values from 3411 onward.

Fixes #6487

* fix(python): compare code objects without inline caches

Fixes #6597

* fix(tests): stabilize process fixtures and malformed input coverage (#6570)

Preserve renamed-executable identity, complete-line readiness and bounded child lifetimes. Use genuinely malformed Inspector input and explicit ADB file-probe/push/hash facts while preserving cancellation, cleanup, Evidence and completeness assertions. Adopt current main Go fixtures and retain malformed COFF coverage.

Fixes #6556
Refs #6480

* test(apktool): own lifecycle fixtures and process observations

* refactor(mcp): reuse parsed Evidence tool parameters

* fix(runtime): align remaining Node security pins and setup guidance (#6316)

Derive exported Docker image versions from .nvmrc through generated package metadata. Align active setup translations with patched Node release floors and verify actual CLI exports, real Docker/agentenv, package and website workflows.

Eight built-test shards pass; three unrelated managed source failures reproduce on clean main and remain tracked in #6650.

Refs #6480

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>

* fix(model): retain exact safetensors shape dimensions

Keep unsigned integer declarations exact until their owning field is interpreted. Bound actual offsets at conversion and validate shape products in declaration order, preserving large empty tensor shapes without hiding an earlier overflow.

Fixes #6627

* fix(python): read legacy TYPE_INT64 marshal values

Fixes #6609

* fix(apk): read constructed BER signer signatures

Share the bounded BER tree reader between PE certificates and APK v1 CMS, then accept constructed OCTET STRING signature values while retaining the declared signer and certificate facts. Embedded X.509 certificate decoding keeps its DER requirement.

Fixes #6603

* fix(adb): count Unicode requested permissions

Count requested-permission rows containing Unicode names, and keep counting subsequent rows in the same dumpsys section.

Fixes #6584

* fix(signals): reject missing sigrok channels

Recognize the exact selected-channel diagnostic even when sigrok-cli exits successfully, while preserving partial producer output in the invalid-input details. Cover both public JSON adapters and add the missing-channel case to the Linux real-tool verifier.

Fixes #6631

* fix(elf): reuse recognized machine architecture facts

Preserve the shared EM_HEXAGON classification in Go and Rust image reports.

Fixes #6629

* fix(asn1): decode four-byte BER lengths unsigned

Accumulate length octets arithmetically so a four-octet length with bit 31 set remains a positive unsigned value and is rejected by the containing-range check rather than becoming a negative length.

* fix(gpu): preserve parameter and target declarations

Decode observed V2 CUDA parameters, retain qualified PTX parameter names and entry resource counts, and preserve family and feature target declarations through selection and consistency checks.

Fixes #6624
Fixes #6625
Fixes #6626
Fixes #6618
Fixes #6613
Fixes #6606

* fix(captures): preserve canonical TShark alias fields

TShark resolves selected field aliases before writing packet JSON. Keep the requested selector in Evidence while accepting the canonical field key produced for it.

Fixes #6595

* fix(qlog): mark records with unknown STREAM FIN incomplete

Keep known STREAM ranges and the unknown FIN value, while listing the source event among incomplete fact records so summary and retained views agree.

Fixes #6598

* fix(pcap): retain absolute HTTP request targets

Reuse parsed URI facts and preserve uncertainty when mixed request records cannot all be resolved from the producer output.

Fixes #6537

* fix(rust): preserve historical cargo-auditable feature facts

Accept observed feature arrays, preserve omitted values as unknown across producer revisions, and keep older retained reports compatible. Reuse bounded JSON sizing before graph expansion.

Fixes #6622

* fix(ptx): normalize parameter declarators once

Fixes #6606

* fix(managed): compare observed call targets

Compare aligned managed call edges by their reported declaring type and method name, keeping missing target facts unknown without comparing build-local tokens. Document the static comparison limits.

Fixes #6630

* fix(artifacts): compare PyInstaller declaration facts

Compare stable producer-tagged declarations independently of materialized payloads. Preserve missing facts as unknown without applying PyInstaller rules to foreign metadata or nested container entries.

Fixes #6484
Fixes #6485

* test(managed): retain derived facts in cloned method fixtures

Clone caller-scoped call and field facts with the fixture methods. Keep known CIL changes alongside unavailable target metadata in the missing-row controls.

* refactor(apk): consume shared BER node facts

Remove the APK reader's pass-through children and content projections so format consumers read the shared BER owner's nodes directly. Keep only the encoded-span helper needed for exact issuer and certificate bytes, and describe CMS BER as this parser's structural owner.

* fix(adb): delimit permission section by indentation

* test(managed): preserve field-access owner identities

* fix(managed): share reference instruction semantics

Use the same parsed method/field operand predicate when producing member edges and comparing call and field shapes. Exclude ldtoken and operands without a value from both interpretations.

* test(managed): align source goldens with metadata validation

Fixes #6650

* fix(native): consolidate observed address validation

* fix(gdb): separate queued work from MI synchronization

Queued console followers have not dispatched MI records. Use active protocol requests when deciding whether the admitted close can verify and detach its inferior.

Fixes #6661

* fix(gdb): wait for the outer console command to finish

After a running result, queue a tokenized read-only MI query to establish that GDB has returned to its command loop. Keep collecting through intermediate inferior stops and retain the query reply as protocol Evidence.

Fixes #6660

* fix(erlang): retain admission cancellation reason

Preserve the caller's AbortSignal reason when BEAM inspection is cancelled before provider admission. Keep the production filesystem boundary and late-completion contracts covered.

Fixes #6658

* fix(desktop): probe GameMaker data filenames

Select conventional Linux and macOS game data files for the existing bounded FORM/GEN8 probe. Add service-boundary regressions and document the selected names.

Fixes #6659

* fix(harmony): exclude raw resources from manifests

Classify known resource paths once and keep a raw resource named module.json from changing the package model or appearing as a manifest. Add a filesystem-boundary regression and clarify the documented hint.

Fixes #6638

* fix(gpu): bound embedded section reads

Fixes #6657

* fix(gpu): retain resources across entry pragmas

Fixes #6651

* fix(reference-source): preserve raw POSIX filename identity

Mark directories with non-UTF-8 names unsupported without following replacement-character paths, while retaining readable sibling observations.

Fixes #6653

* fix(reference-imports): retain exact dynamic import targets

Use the shared exact-literal reader for dynamic imports, preserving expression-free templates and transparent TypeScript wrappers while leaving computed targets unknown.

Fixes #6654

* fix(reference-imports): retain exported import-equals dependencies

Route exported external import-equals declarations through the same relationship owner as plain declarations so their required target is not dropped.

Fixes #6655

* fix(managed): respect native module case semantics

Preserve the observed native format when comparing module identities so ELF case-only differences remain mismatches while unknown platform behavior stays unresolved.

Fixes #6652

* fix(il2cpp): reject duplicate method tokens per image

Reject duplicate MethodDef row identities within one owning image before publishing native addresses or Ghidra seeds, while retaining cross-image reuse and folded code addresses.

Fixes #6610

* refactor(reference-imports): share exact literal parsing

Route legacy nested import-expression handling through the same exact-literal owner as dynamic imports, removing a duplicate string-only check.

Fixes #6654

* fix(model): preserve optional metadata and tensor alignment

Fixes #6656
Fixes #6637
Fixes #6636

* fix(macho): infer legacy Intel simulator platforms

Fixes #6649

* fix(macho)!: preserve ambiguous chained import names

Keep the exact producer expression and report unknown symbol identity when chained-import text cannot distinguish a binding addend from a literal name suffix.

Fixes #6648

BREAKING CHANGE: inspect_macho import names can be null when identity is ambiguous. Use raw_name for the observed expression and name_status to distinguish it from an exact symbol name.

* fix(elf): retain raw export name bytes

Fixes #6647

* refactor(macho): separate dyld import and export parsing

Keep mode-specific inputs and parsed row types at their respective parser boundaries.

* fix(macho): preserve import identity in retained views

Use distinct row contracts for imports and exports, retaining ambiguous names and historical import defaults without adding import-only fields to export pages. Verify the SDK-advertised schemas and both facets through MCP.

* style(desktop): format GameMaker probe coverage

* chore(deps): update Vite security patch and dependency inventory (#6416)

Update Vite/PostCSS and refresh the lock-derived inventory while retaining TSRS platform selection and runtime dependency versions.

Source/static checks, installed-platform signatures, full/production audits, real CLI/MCP workflows and all four package platforms pass. Portable CI retains the independently reproduced main PTX fixture failure tracked in #6675; use the owner-authorized existing PR-only baseline exception. Refs #6480.

* fix(release): isolate npm publication from dependency execution (#6681)

Keep dependency execution in read-only release jobs and validate the original qualified archive with Node built-ins before publication. Refresh registry state on every publisher attempt; retain exact bytes/channel verification, v1 read-only recovery, and installed CLI/MCP checks before MCP publication.

Static/docs checks, artifact/registry/recovery tests and real package/rehearsal verification pass. All four hosted package platforms pass. Portable CI retains the independently reproduced main PTX failure in #6675 and fail-fast missing coverage; use the owner-authorized existing PR-only exception, with limitations documented in the PR. Refs #6480.

* refactor(json): consolidate representation size accounting

Share bounded UTF-8 and UTF-16 JSON measurements across state serving, write retention and source-map admission. Remove duplicate counters and distinguish retained state estimates from encoded bytes while preserving limits and exact refusal diagnostics.

* refactor(android): own search summaries at the producer boundary

Reuse validated class pages for inline pagination audits while retaining complete provider replies. Move retention into the shared Android workflow and remove the MCP-only service wrapper and application text reparser. Preserve unknown JSON metadata, late cancellation and retention failures.

* test: align boundary fixtures with producer contracts

Model GDB console completion, use real directory reads and cleanup for late-enumeration failures, and distinguish supported PTX pointer qualifiers from unknown declarations. Preserve original assertion and cleanup failures through scoped test finalizers.

* fix(rust): retain parsed defaults in cached Evidence views

Borrow sealed reports only when they match the parsed facts; otherwise cache the owned normalized snapshot. Keep historical feature omissions unknown through saved bundles and repeated retained pages without changing the source Evidence.

Fixes #6689

* fix(model): retain parsed headers when hashing is interrupted

Share partial observation ownership across GGUF and Safetensors. Preserve completed header facts through cancellation and MCP error delivery without claiming finalized digests or file identity.

Fixes #6684

* fix(gpu): preserve PTX parameter and target facts

Fixes #6664
Fixes #6675
Fixes #6680
Fixes #6695

* fix(go): read inline build strings from ELF mappings

Fixes #6716

* fix(rust): scan read-only ELF load data

Fixes #6663

* fix(il2cpp): deduplicate consistent ELF registration aliases

Fixes #6715

* fix(il2cpp): track unresolved ELF relocation widths

Fixes #6701

* fix(artifacts): preserve raw directory name identity

Fixes #6665

* fix(desktop): retain unsupported filename coverage

Fixes #6665

* fix: preserve unknown historical module resolution

Fixes #6679

Fixes #6678

Fixes #6612

* fix: retain proven createRequire URL bases

Fixes #6612

Fixes #6678

* fix(apple): preserve keyed archive table identity

Fixes #6662

* fix(plist): reject XML dictionary keys without values

Fixes #6682

* fix(apple): preserve NIBArchive special real values

Fixes #6583

* fix(signals): reject missing targets and invalid UTF-8

Fixes #6671

Fixes #6693

* fix(beam): accept bytes after declared form

Fixes #6717

* fix(artifacts): compare source map target identity

Fixes #6706

* fix(pyinstaller): retain executable member metadata

Fixes #6702

* fix(pyinstaller): decode interned unicode names

Fixes #6676

* fix(pyinstaller): retain colliding archive observations

Keep source-distinct CArchive rows and decoded PYZ children in inventory. Refuse only when extraction reaches a destination conflict.

Fixes #6674

* fix(dotnet): preserve managed metadata comparison facts

Decode VARARG sentinels and allow omitted empty blob heaps while retaining failures for referenced missing data. Compare field and catch targets using owning parsed facts instead of build-local tokens.

Fixes #6720
Fixes #6686
Fixes #6713
Fixes #6712

* fix(dotnet): keep TypeRef catch identity unknown

Fixes #6712

* test(apple): assert projected interface builder facts

* fix(dotnet): correct metadata comparison regressions

* fix(il2cpp): deduplicate aliased registration fields

Fixes #6715

* test(pyinstaller): match interned name producer encoding

Use Python 3.13 PYZ magic with the matching archive version and exercise FLAG_REF with TYPE_INTERNED.

Fixes #6676

* test(dotnet): split managed comparison blocks

* test(apple): isolate NIBArchive real projection group

* fix(parsers): correct Rust import and PTX alignment control

* fix: recognize aliased createRequire bindings

Fixes #6612

Fixes #6678

* test(apple): retain NIBArchive limitation path

* fix(il2cpp): deduplicate aliased metadata registration

Fixes #6715

* test(managed): retain observed target changes across member remaps

* fix: track require.resolve references

Fixes #6678

* test(pyinstaller): encode PYZ list length correctly

Write the marshal list length as its raw little-endian count and surface inventory limitations when completeness regresses.

Fixes #6676

* fix(managed): retain unknown catch identity beside observed name changes

* fix: retain require.resolve source facts

Fixes #6678

* refactor(javascript): name retained require call facts explicitly

* fix: resolve selected require call members

Fixes #6678

* fix(javascript): keep unresolved created-loader bases unknown

* refactor(artifacts): centralize completed file outcomes

Project completed values and cancellation from the descriptor owner once across artifact consumers. Preserve completed void outcomes and format-specific validation and cleanup policies.

Keep later aborts from replacing captured APK and SQLite close failures, and retain the exact APK cancellation reason. Exercise real descriptors, public workflows and cleanup retries.

* fix(javascript): isolate package facts from host prototypes

Build frozen package field snapshots with a null prototype and restrict reference-source main lookup to own properties. Preserve declared null and empty values, index fallback, source identity and unavailable manifest evidence.

Compare inherited main and exports lookup with the native Node resolver, retain package observation coverage and verify CLI/MCP package workflows.

* fix(captures): advertise offline capture inspection without a browser provider (#6725)

* fix(parsers): preserve format boundaries and query occurrence identity

Normalize parsed facts at their owning boundaries across PE exports and certificates, ELF section names, GPU bundles, IL2CPP generic types, dyld slice selection, source maps, environment replay, and JavaScript mapped arguments. Preserve partial facts and explicit unsupported cases; clarify the corresponding documentation.

Validation: 831 affected tests passed with one existing skip across 23 files; build, typecheck/lint, documentation, formatting, and 2133-file test discovery passed. Format controls are synthetic; real Unity, GPU, and ARM-device execution is unverified.

Fixes #6709
Fixes #6688
Fixes #6719
Fixes #6718
Fixes #6704
Fixes #6703
Fixes #6692
Fixes #6723
Fixes #6687
Fixes #6726
Fixes #6696
Fixes #6691
Fixes #6727

* fix(process): require observed environment ownership tokens

Centralize run-token extraction at the environment observation boundary and require an own field. Build decoded OS environment records without host prototypes while retaining source names, empty values and last-assignment precedence.

Reject inherited matching tokens before cleanup signaling, preserve normal owned-group behavior, and verify live Linux process environments alongside native CLI/MCP capture workflows.

* fix(parsers): retain independent facts and boundary identity

Share bounded ELF section-name decoding across native and note readers; retain read-only ranges and coverage reasons when names are unknown. Preserve ELF symbol-version bytes, dyld-bound method uncertainty, partial gRPC-Web trailers, and per-parent model identity checks. Compare GPU signatures as bytes and require a PTX module header. Share selected-path errno classification across EVM and BEAM.

Validation: 397 shared-parser tests passed (one existing skip), 5 MCP schema tests passed, 14 EVM error-mapping tests passed, and 23 protobuf CLI/MCP matrix cases passed across focused runs. Build, typecheck/lint, docs, formatting, and 2134-file discovery passed. Full EVM provider workflow remains locally unverified on Darwin arm64; format controls are synthetic.

Fixes #6738
Fixes #6737
Fixes #6745
Fixes #6740
Fixes #6749
Fixes #6747
Fixes #6739

* fix(setup): preserve source keys across configuration boundaries

* fix(setup): keep the CLI-only skill choice offered under a client ID (#6401)

* fix(setup): keep the CLI-only skill choice offered under a client ID

* test(setup): cover the accept-all CLI-only skill selection

* fix(apple): report a read-denied selected archive as host access denial (#6479)

* fix(apple): report a read-denied selected archive as host access denial

inspect-keyed-archive reported a host read refusal on the caller-selected bundle entry as artifact_operation_failed/execution_failure with reason io, leaving EACCES or EPERM only inside message text. The caller selected that entry, so the refusal is a selection outcome with its own typed classification, system code and read-access recovery.

DirectoryArtifactReader now marks a refused entry open with DirectoryArtifactEntryAccessDenied, which retains the host system code and the selected entry path. KeyedArchiveReader, which owns the caller's selection, maps it to the shared AnalysisAccessDeniedError, and artifact failure translation keeps that typed error instead of replacing it with a generic io failure. Other readers and other reader failures are unchanged; every existing reason keeps its current projection.

Adds the access_denied projection coverage plus a real host refusal through the production reader and a non-permission control.

* fix(apple): carry cleanup ownership and cover raw refusals for a denied selection

Addresses the two review findings on the denied-selection classification:

- The typed host access denial now carries the reader's cleanup observation, so a denied open that left a resource owned does not project as fully cleaned.
- Adds coverage that starts from raw host EACCES/EPERM/EIO refusals with the real DirectoryArtifactReader open path, so the marker itself is exercised rather than constructed by the test. EIO stays an artifact failure.

* fix(native): report plist symlink loops and overlong paths as selection failures (#6371)

Co-authored-by: Abelo9996 <Abelo9996@users.noreply.github.com>

* docs(cli): document opt-in Bash completion setup (#6250)

* fix(doctor): check only the current platform's Hopper launcher candidates (#6253)

* fix(doctor): check only the current platform's Hopper launcher candidates

Doctor built one launcher list for every platform, so on macOS it could
report a Linux-only path as a healthy Hopper ahead of a renamed bundle,
and setup then registered that path. Give per-platform automatic
candidates one owner that runtime configuration and doctor both read,
scan renamed macOS bundles and probe the Homebrew cask only on macOS,
and share runtime's renamed-bundle scan with the doctor host.

Fixes #6228

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(doctor): keep the renamed Hopper bundle scan asynchronous

Sharing runtime's synchronous scan made the doctor host read
~/Applications with readdirSync, which blocks the event loop on a slow
or network-mounted home. Give MacHopperPaths an asynchronous scan for
doctor beside runtime's lazy synchronous one, sharing the directory
filter and candidate builder, and check that both return the same
candidates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(doctor): model renamed launchers with runtime's POSIX joins

Since #5235, runtime builds macOS launcher paths with posix.join, so on
Windows the discovery table's native-join renamed launcher no longer
matched runtime's candidate. Model launchers with posix.join and keep
filesystem setup native, as MacHopperPaths.test.ts does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(entropy): name offset when the byte window starts past EOF (#6495)

Fixes #6482

Co-authored-by: Abelo9996 <Abelo9996@users.noreply.github.com>

* fix(sqlite): report result-column capacity refusals as capacity (#6327)

A projection wider than SQLite's native result-column limit failed with the
generic "too many columns in result set" SQL error. The inspector could not
attribute that error to a generated column, so the worker reported "format"
and the parent blamed the caller's path as invalid_format even though the
selected database was readable.

Classify the refusal from SQLite's own column limit for the private
connection, carry the selected and engine counts through the worker reply,
and project it as a capacity resource constraint. The database stays
readable, no partial rows are returned, and the recovery names the column
counts and splitting the projection across calls.

* fix(web): refuse an existing script-export destination as invalid input (#6313)

* fix(web): refuse an existing script-export destination as invalid input

export_web_scripts refused an existing output directory or link correctly,
but reported it as artifact_operation_failed / execution_failure with no
field issue or recovery. SafeOutputTree.create raises that refusal as a
path failure before any output tree exists, and the export mapper wrapped
it as an artifact failure.

Attribute pre-admission path refusals to output_directory as an
AnalysisInputError, as environment export already does for its directory.
Both now share one helper owned beside SafeOutputTree; failures after the
tree is admitted keep their artifact semantics.

Fixes #6029

* fix(artifacts): type SafeOutputTree destination refusals

Admission conversion treated any cleanup-free path failure raised before
admission as a refusal of the selected directory, so an acquired-tree setup
failure, such as being unable to restrict a created root to 0700, blamed
valid output_directory or directory input.

SafeOutputTree.create now raises SafeOutputTreeDestinationRefusal for the
refusals of the selection itself: a relative or reserved root, an existing
root, and an accepted existing root that is not an empty directory. The shared
conversion accepts only that type, directly or wrapped by
SafeOutputTreeCreationFailure, so script and environment export no longer
track admission separately.

* fix(evm): reject repeated container keys in Solidity metadata (#6230)

* fix(evm): reject repeated container keys in Solidity metadata

* test(evm): check the repeat-key diagnostic for deeply nested keys

* docs(ci): add a repeatable static analysis example (#6496)

* docs(ci): add a repeatable static analysis example

* fix(ci): isolate example reports and repair the guide link

---------

Co-authored-by: gongfpp <22683417+gongfpp@users.noreply.github.com>

* fix(setup): retain unresolved environment facts when deriving budgets

* fix(parsers): preserve format evidence and caller input identity

Retain bounded FAT and offset-tagged PE observations through archive hashing,
classification, and content nodes. Preserve PyInstaller member paths according
to the observed carrier dialect and share APK v1 signing-name semantics.

Read SQLite's implicit sqlite_schema table without inventing a stored schema
declaration. Distinguish unsupported ELF numbering and decoded-name admission
from malformed data and fixed scan allowances. Preserve Sigrok basenames and
classify matching explicit input-format refusals at their owning boundary.

Validation: 554 distinct tests passed, 3 skipped across serial focused runs;
build, typecheck/lint, docs, formatting, and discovery (2141 files) passed.
Sigrok command-boundary simulators do not establish real-tool decoding.
Small repeated public PyInstaller CLI runs had equivalent inventory facts;
warm median elapsed 0.5431s before / 0.5426s after, with no speed claim.

Fixes #6733
Fixes #6741
Fixes #6722
Fixes #6732
Fixes #6736
Fixes #6734
Fixes #6764
Fixes #6766
Refs #6739

* fix(parsers): respect container facts and real decoding boundaries

Use zip.js's parsed symlink fact for inventory and open refusal. Treat an
unmatched Godot trailer as an unconfirmed candidate while preserving failures
for confirmed malformed packs. Report entropy path-resolution failures at the
selected-input boundary.

Separate Go header discovery from inline string extents in ELF and Mach-O,
and apply the aggregate content allowance after validating real source ranges.
Normalize binary plist UID widths through the existing scalar-copy owner,
budget exact clone growth, preserve source identity, and refuse inexact UIDs.

Validation: 389 distinct tests passed, one Linux /proc test skipped on Darwin;
build, typecheck/lint, docs, single-thread formatting, and discovery (2142 files)
passed. CLI/MCP Go fixtures and public ZIP/Godot/keyed-archive workflows ran.
Real producer prevalence and external provider execution were not established.

Repeated ordinary keyed-archive CLI inventory facts and estimated reply tokens
were equal before/after. Warm median elapsed was 0.5166s / 0.5177s; no speed claim.

Fixes #6751
Fixes #6763
Fixes #6754
Fixes #6767
Fixes #6762
Fixes #6779

* refactor(mcp): consolidate Evidence recording and operation progress

* fix(setup): reuse URL component admission for Hopper releases

* perf(cli): avoid loading analysis commands for version reports

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
Co-authored-by: Hifza Zafar <152292315+hifzabuildsai@users.noreply.github.com>
Co-authored-by: Can <159528514+eco-null@users.noreply.github.com>
Co-authored-by: eco-null <eco-null@users.noreply.github.com>
Co-authored-by: Cassie_Fox <249835913+CassieFox23@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Wade <160517347+Sriram-PR@users.noreply.github.com>
Co-authored-by: RRFZ <247457381+Plastic-time@users.noreply.github.com>
Co-authored-by: pablodiazjorge <102741971+pablodiazjorge@users.noreply.github.com>
Co-authored-by: Ezra Brilliant <64943463+ezrabrilliant@users.noreply.github.com>
Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: GamerDubz <105694977+GamerDubz@users.noreply.github.com>
Co-authored-by: raidnouredden-ux <raidnouredden@gmail.com>
Co-authored-by: 吴佳浩Alben <35291372+XiaoBinGan@users.noreply.github.com>
Co-authored-by: Abel Yagubyan <abelyagubyan@berkeley.edu>
Co-authored-by: Abelo9996 <Abelo9996@users.noreply.github.com>
Co-authored-by: ShuaixinHuang <1836656514@qq.com>
Co-authored-by: Paritosh Lahre <155938586+SandstromPL@users.noreply.github.com>
Co-authored-by: Dery Ferdika <114888155+DeryFerd@users.noreply.github.com>
Co-authored-by: gongfpp <1360187968@qq.com>
Co-authored-by: gongfpp <22683417+gongfpp@users.noreply.github.com>
2026-10-24 00:06:03 +08:00

40 KiB
Raw Blame History

CLI and Evidence

Use the CLI for a direct inspection or a script. It uses the same application workflows and evidence contracts as REA's MCP server. Each CLI invocation is a separate process; save results when you want to use them in a later command. For a pinned, noninteractive workflow with retained reports, see static analysis in GitHub Actions.

Run a command

After installing REA, use rea. You can also run a command without a global installation:

npx -y rea-agents@latest analyze-javascript-application /absolute/path/to/app --json

Use an extracted application directory or an ASAR as the target. Static JavaScript analysis returns the application graph and Evidence directly. Generic rea analyze PATH selects this workflow for directories and .asar files when neither --provider nor --snapshot is supplied. See JavaScript artifact reconstruction for results, integrity checks and coverage.

The complete application Evidence can be hundreds of megabytes for a real application. When an agent or a person reads the result, save it to a file and project a summary, a module page or one module from the saved Evidence:

rea analyze-javascript-application /absolute/path/to/app --json > app-evidence.json
jq -c '{source: {kind: "inline", evidence: .}, view: {kind: "summary"}}' app-evidence.json > app-view.json
rea inspect-analysis-view app-view.json

The request can also name the saved file instead of embedding it: {"source": {"kind": "evidence-file", "path": "app-evidence.json"}, "view": {"kind": "summary"}}. The CLI resolves a relative path against the working directory; MCP clients pass an absolute path. REA reads and authenticates the file, then projects it like retained Evidence, so a large file is bounded by the file reader rather than charged as inline input.

For example, a 334 MB Obsidian application Evidence file yields a summary view of about 10 KB. Replace the view with {"kind": "page", "collection": "modules", "offset": 0, "limit": 32} for a module page. See JavaScript application workflows for views, feature traces and comparisons that take the same saved Evidence.

Shell completion

The CLI includes optional shell completion. Run rea completions --help to see the available shells and their setup commands. For Bash, load the hook into the current shell:

eval "$(rea completions bash)"

The current Bash hook requires support for complete -o nosort; macOS's system Bash 3.2 cannot load it. Use a newer Bash for this hook.

For future interactive non-login Bash sessions, add the command to ~/.bashrc. Interactive login Bash sessions read the first available file in ~/.bash_profile, ~/.bash_login, and ~/.profile; add the command to the file your shell reads, or have that file source ~/.bashrc. Remove the command from the startup file to stop loading completion, and run complete -r rea to remove the registration from the current shell. These are manual, opt-in steps. Completion is a discovery aid; use rea COMMAND --help to confirm the available options and subcommands.

Managed assemblies (.NET)

For a .NET PE/CLI assembly, inspect its identity and deployment form before inspecting members. These commands read metadata and Common Intermediate Language (CIL) without loading or executing the assembly and require no native analysis engine:

rea inspect-managed-artifact /absolute/path/Assembly.dll --json
rea inspect-managed-members /absolute/path/Assembly.dll --json
rea inspect-managed-members /absolute/path/Assembly.dll --type Example.Parser --json

Replace Example.Parser with an exact full_name from the member inspection, or a declaring type name you already know. Omit --type to inspect all members, or repeat it to select several types. Selection limits decoding to the selected types; member references remain an assembly-wide inventory, so the output can still be large.

Select --detail summary --evidence-bundle /absolute/path/members.json to receive identity, selection, coverage, limitations and collection counts while saving the complete original Evidence in a new bundle. Summary requires that explicit destination; existing files are preserved. Later inspect-analysis-view calls can page the exact parent from the saved bundle without reopening the assembly. See CLI summary and saved member rows for the complete command sequence. Omitted or --detail complete retains the full inline response.

Choose the workflow from the artifact's contents rather than its .exe or .dll extension. The managed parser requires PE/CLI metadata; it does not unpack .NET single-file hosts or decode IL2CPP. For the image, type and method names in a Unity global-metadata.dat, use IL2CPP metadata. NativeAOT method bodies require native analysis. See the managed-code guide for supported deployment forms, selection semantics, and coverage limits.

SQLite snapshots

For a local database snapshot, use rea inspect-sqlite-database PATH --json. Add --table NAME --row-limit 20 to read a bounded sample from an ordinary table. This command does not require a native analysis provider. See SQLite database snapshots for database/WAL identity, source-file handling and row-value semantics.

Native analysis

Inspect embedded Go build metadata without installing Go or configuring a disassembler:

rea inspect-go-binary /absolute/path/to/program --json

The shared CLI/MCP workflow reports compiler version, modules, replacements, build settings, original bytes and SHA-256. See Go binaries for supported containers and absent or malformed metadata.

Inspect a Godot PCK without running the game:

rea inspect-artifact game.pck --detail summary --evidence_output evidence.json --json
rea extract-artifact game.pck --json

Formats 2, 3 and 4 retain header, directory and integrity facts. Compact delivery keeps complete Evidence in the requested bundle. See Godot PCK for embedded packs, batch queries and unknown encrypted coverage.

Inspect local model declarations without loading weights:

rea inspect-model-artifact /absolute/path/model.gguf --json
rea inspect-model-artifact /absolute/path/model.safetensors --hash full --json

Default hashing reads only headers and leaves full-file identity unknown. --hash full streams the complete file for SHA-256. Both return typed metadata, original tensor declarations and derived totals. MCP summaries retain complete Evidence for filtered metadata, tensor and type-total pages; CLI compact delivery uses --detail summary --evidence_output FILE. See model files.

Inspect Unity IL2CPP metadata names without Unity or a disassembler:

rea inspect-il2cpp-metadata /absolute/path/global-metadata.dat --json

The command decodes a version 24, 27, 29, 31 or 39 global-metadata.dat and reports assembly images, type, method and member names, string literals, index ranges, header sections and SHA-256. With --binary PATH it also reads the matching GameAssembly.dylib, GameAssembly.dll or libil2cpp.so (never runs it) and links each method to its code address; --ghidra-seeds PATH then writes Ghidra function seeds. It does not decrypt metadata. MCP defaults to compact counts with retained Evidence; query indexed rows with filters, batch indices and selected fields. The CLI defaults to complete Evidence; --detail summary --evidence_output FILE exports the full result to a new file and returns a compact overview. See IL2CPP metadata.

Inspect an embedded cargo-auditable Rust dependency list without installing Rust or configuring a disassembler:

rea inspect-rust-binary /absolute/path/to/program --json

The same workflow reports package names, versions, sources, the root package, dependency edges, and the section's file range. A missing .dep-v0 section is null metadata, not proof that the binary has no dependencies. See Rust binaries.

Inspect a PE Authenticode certificate table without executing the image or verifying signatures:

rea inspect-pe-certificates /absolute/path/to/application.exe --json

The workflow reports WIN_CERTIFICATE entries and, for PKCS#7 signedData, embedded X.509 serial, issuer, subject, and validity fields. A missing security directory is observed absence of that table. See PE Authenticode certificate tables.

Inspect ELF PT_NOTE and SHT_NOTE tables without executing the image:

rea inspect-elf-notes /absolute/path/to/program --json

The workflow reports note owners, types, descriptor hashes, and GNU build-id or ABI-tag fields when those descriptors match. A missing note table is observed absence of those declarations. See ELF note tables.

Inspect a CPython 3.7–3.13 .pyc header and nested marshal code objects without executing bytecode or installing Python:

rea inspect-python-pyc /absolute/path/to/module.pyc --json

The workflow reports the pinned CPython version for the magic, PEP 552 hash or mtime/size fields, nested function names, and bytecode SHA-256. Bytecode is not decompiled. See CPython pyc inspection.

Inspect an Erlang BEAM file without executing bytecode:

rea inspect-erlang-beam /absolute/path/to/app.beam --json

The workflow reports IFF chunk names, atom tables, exports, imports, lambdas, and the Code chunk header. Missing optional tables stay null. See Erlang BEAM files.

Configure Hopper or Ghidra, the IDA adapter, or Kuna before analyzing a native target. Substitute your target, search text and function name or address in these examples:

rea analyze /absolute/path/to/program --provider ghidra --json
rea search /absolute/path/to/program "search" --provider ghidra --json
rea function /absolute/path/to/program main --provider ghidra --json
rea decompile /absolute/path/to/program 0x1000 --provider ghidra --json
rea xrefs /absolute/path/to/program 0x1000 --provider ghidra --json
rea trace /absolute/path/to/program "search" --provider ghidra --json

analyze and inspect share the native overview workflow. function returns a function dossier; decompile returns pseudocode. For assembly instructions alone, use rea instructions. A macOS .app bundle can be supplied directly.

Run rea --help or a command's --help for arguments and output options. The generated catalog lists all CLI commands and MCP tools. Provider-specific target support is described in the native guide, DOS guide, raw binary guide, and Windows Ghidra guide.

Choose a provider

List the available providers and their supported operations:

rea providers --json
rea capabilities --json

These commands describe binary-session providers and auxiliary capabilities. For the complete MCP surface, use the connected server's tool list and the session's advertised availability; individual guides describe prerequisites.

With automatic selection, REA uses the single available provider that supports the target. When several providers support it, select one explicitly:

rea analyze /absolute/path/to/program --provider hopper

Set REA_ANALYSIS_PROVIDER for a standing preference. An explicit --provider overrides it. In MCP, pass provider_id to open_binary:

{
  "path": "/absolute/path/to/program",
  "provider_id": "hopper"
}

The selected provider remains bound to the session until an explicit switch or close. Provider failures are returned with their original reason. For an ambiguous selection error, choose from details.candidate_ids; for provider_unavailable, follow message, remediation.action, and the original reasons in details.rejections. For Hopper, Ghidra, IDA, JADX, and Kuna, run rea doctor --provider ID --json to diagnose the selected engine. Other adapters, such as pwntools-elf, report their configuration requirements directly and are not accepted by doctor --provider. See task readiness and provider selection.

The session reports work still in progress through analysis_activity. A client timeout can end its wait while the provider continues analyzing. cleanup_incomplete identifies resources whose shutdown or removal could not be verified. See MCP contracts for session lifecycle and Ghidra first-query deadlines for import, client timeouts and recovery.

If one-shot analysis fails and closing its session also fails, the original error details remain inline and details.cleanup_error describes the later close failure. Each diagnostic retains its own reported resources; the later failure does not establish whether an earlier resource was released. Captured output and partial observations remain in the original details.

Save and reuse analysis snapshots

A snapshot retains successful analysis results for later queries. REA reuses an exact result when the target bytes, operation, parameters, provider and settings match. Mutations and cursor-dependent calls are excluded from the cache. Snapshot files are local and use owner-only permissions.

Dispatching a metadata write invalidates the active session's snapshot cache, even if its reply fails: the provider may already have applied the write. Close and reopen the target before importing or saving another snapshot.

Snapshots retain eligible target-scoped question histories in full, including mutation Evidence recorded while another target was active. Observations and related questions must still belong to the saved target. If those dependencies cannot be retained, the entire history is excluded instead of reverting the question to an earlier revision or disposition.

rea analyze /absolute/path/to/program --provider ghidra --snapshot /absolute/path/to/analysis/program.json
# Repeat the same query to reuse its saved result.
rea analyze /absolute/path/to/program --provider ghidra --snapshot /absolute/path/to/analysis/program.json

An exact CLI cache hit is normally read before starting a provider process. On Windows, Ghidra first admits the selected source through its native snapshot owner, so replay can start that provider. In MCP, open_binary accepts snapshot_path to import a snapshot atomically for its matching target; an MCP provider may still start before returning a cached result. close_binary accepts snapshot_path and optional overwrite: true to save before releasing provider resources. A failed save leaves the session open so the caller can resolve the output failure.

The MCP save receipt reports primitive_entries, workflow_entries, and evidence_records separately. Zero primitive bindings can still accompany retained workflow results and Evidence. These are cached observations, not a saved provider database: only eligible exact queries can reuse a result, and new or live queries can still require provider startup. The CLI uses the same snapshot format and preserves these records when loading and updating it.

Import, export and compare Evidence

Evidence records retain artifact identity, source locations, observations, inferences and unresolved findings. Validate an existing bundle, export its canonical form, or compare two supplied bundles:

rea evidence-import /absolute/path/to/evidence/bundle.json
rea evidence-export /absolute/path/to/evidence/bundle.json /absolute/path/to/evidence/canonical.json
rea compare /absolute/path/to/evidence/left.json /absolute/path/to/evidence/right.json

Exports preserve an existing destination unless --overwrite is explicit. For application traces and version comparisons, see JavaScript application workflows. MCP retained Evidence references belong to one connection. Separate CLI calls can consume full saved records. inspect-analysis-view REQUEST.json --evidence-bundle BUNDLE.json resolves the request's retained-evidence source ID from that authenticated bundle, including bundles exported from an MCP session. The same view JSON works for every supported parent kind; no target is reopened and no record is selected by file order. Omit --evidence-bundle when the request supplies inline Evidence.

Import historical source

Import an older source tree to compare with the current artifact:

rea import-reference-source /absolute/path/to/source
rea import-reference-source /absolute/path/to/source --detail summary --outline-depth 2 --json

The default (--detail full) returns the complete HistoricalSourceGraph. Choose --detail summary for a HistoricalSourceSummary of that same committed inventory: its HistoricalSourceManifest contains the full graph and root digests, with provenance, VCS facts, languages, manifest paths, entry and relationship counts, parse-failure counts, file/directory states, exclusions and limitations. The summary is a presentation view, not a graph accepted by source-to-bundle comparison; keep the full output for that workflow.

--outline-depth requires --detail summary and accepts a nonnegative safe integer. Depth 1 shows root children, depth 2 (the default) also shows their children, and depth 0 omits all outline entries. Paths retain canonical Unicode code-point order. outline.omitted_entry_count counts only inventoried entries hidden by the chosen depth; it does not count unexamined children of excluded or unreadable directories, or change inventory_state. Exclusions and source limitations remain separate from this presentation omission.

file_sizes.known_bytes is the exact sum of known inventoried file sizes as decimal text, so large sums cannot lose integer precision. Unknown sizes count in file_sizes.unknown_file_count; excluded or unexamined paths are not included in that total. A zero known-byte sum therefore does not establish an empty source tree. Full output retains individual file hashes, relationships and parse-failure diagnostics. Summary mode performs the same import and cleanup, then projects the committed result without rereading source files. It reduces the selected output, not the amount of source examined. A shallow tree or many exclusions can still produce a large summary; depth 0 removes the outline but preserves the other facts. No fixed output-size or runtime improvement is promised.

The import records hashes and metadata for the supplied files, separately from observations of the current app. For a directory inside a Git checkout, it records the HEAD of the nearest enclosing repository; whether the working tree matches that commit remains unknown. It honors the source tree's .gitignore and applies default exclusions for common generated and dependency paths such as node_modules/, dist/, and *.log. Pattern-based exclusions record the matched pattern and whether it came from project, default, caller, or sensitive path policy. Links into excluded paths retain their internal target metadata; the exclusion explains why the target has no inventory entry, and the inventory remains partial. Exclusions record entry_kind when the importer observed it; older saved exclusions without that field have unknown kind. An excluded ancestor proves an internal descendant only when its kind is directory. Set REA_REFERENCE_SECRET_PATTERNS_JSON to a JSON array of ignore patterns when you want to mark selected paths as sensitive; those patterns are reported separately as configured-secret exclusions.

Re-import saved graphs whose pattern-based exclusions lack pattern before using them in source-to-bundle comparisons.

Entries that change during an import retain an unavailable-entry diagnostic alongside readable siblings. If enumeration of an already admitted root fails, the graph keeps its observed children and records the root failure as a top-level limitation. That partial inventory does not establish absence among unexamined children. POSIX directory-entry bytes that are not valid UTF-8 cannot be represented as graph paths; the containing directory (or root) is marked unsupported, and REA does not access the entry through a replacement-character name. Readable siblings remain inventoried.

JavaScript and TypeScript import parsing requires valid UTF-8. Malformed source bytes retain their original hashes and sizes with a decoding diagnostic; REA does not infer module targets from replacement characters. Exact dynamic-import strings, expression-free templates and runtime-transparent TypeScript wrappers retain their targets; computed imports remain unknown. TypeScript import-equals dependencies remain requires relationships whether or not they are exported.

REA derives historical CommonJS paths only when the selected loader and its base are proven: this includes the exact createRequire(new URL("./file.cjs", import.meta.url)) form and require.resolve with { paths: [__dirname] }. Other custom bases and search options remain partial with unknown resolution and the literal requested specifier. Overwritten resolver methods retain that uncertainty; they are not attributed to Node. require.main is a module object, so calling it does not establish a loader reference. These relationships do not establish execution; Node's require.resolve performs lookup without loading the target. An excluded package.json also leaves package-directory selection unknown rather than treating the manifest as absent and applying an index fallback.

Historical-source import requires safe no-follow file opens on Linux or macOS. Native Windows returns unsupported_host; use Linux REA inside WSL or another supported host. See source-to-bundle comparison for mapping identities, inferences and unknowns.

Capture runtime behavior

Choose the guide for the target and intended interaction:

Runtime requests name the target and actions. Launched targets run with your user permissions; consult the chosen guide for host requirements and effects.

Serve MCP over streamable HTTP

rea mcp speaks stdio to the client that launched it. To serve the same MCP catalog over streamable HTTP for one local client, such as an agent environment runtime, start the dispatcher entry with --http:

rea mcp --http --port 8765

--host and --port default to MCP_HOST and MCP_PORT from the environment, then to 127.0.0.1 and an ephemeral port. The bound URL is written to stderr as one JSON log line ("msg":"MCP transport listening") whatever REA_LOG_LEVEL is set to; nothing is written to stdout. rea mcp --http --help lists the accepted options. The listener serves one client at a time: a session ends with the client's DELETE, and a client that connects while another session is open takes it over, so a client that exited without ending its session needs no restart. The listener runs until SIGINT or SIGTERM and does not stop when stdin closes. See transports for the session, Host header and shutdown contract. Client registrations written by setup and the MCP registry entry keep stdio.

Serve an environment manifest

rea environment-serve <manifest.json> --evidence <capture.json> [--replay-only] [--host H] [--port N] serves an environment manifest projected by inspect-analysis-view as an agent environment: an MCP server at /mcp, the environment card at /.well-known/agent-env.json, and a /agentenv data plane. The manifest's parent_evidence_id must equal the evidence file's evidence_id; otherwise the command refuses with invalid_request before binding. Before binding it derives the environment-state view of the capture with the manifest's template_rules, as inspect-analysis-view would, and serves from it: read tools whose views are state-backed answer from a live state, write tools are served only where the capture's later reads confirmed their effect, and /agentenv serves data/reset, data/add and data/get. When the state cannot be derived, or its catalog exceeds the discovery reservation, it logs a warning with the error code and message and serves replay; --replay-only serves replay without deriving. In replay every manifest tool replays the retained capture records it cites and /agentenv answers every method with JSON-RPC -32601. The stopped document's state member is {"served": true, "evidence_id": …}, {"served": false, "reason": "replay-only"} or {"served": false, "reason": "unavailable", "code": …, "message": …}; see serve from the state.

rea environment-serve manifest.json --evidence capture.json --port 8765

--host and --port resolve like rea mcp --http: flags, then MCP_HOST and MCP_PORT, then 127.0.0.1 and an ephemeral port. ENVIRONMENT_NAME renames the served environment; set but blank, it is refused as configuration_invalid like a blank MCP_HOST. The bound URL is written to stderr as one JSON log line ("msg":"MCP transport listening"). See agent environments for what the state and replay return and do not establish.

Export an environment bundle

rea environment-export <manifest.json> --evidence <capture.json> <dir> [--package-tarball <path>] [--name <override>] writes the same manifest and capture pair as a bundle folder the agentenv framework runs with agent-env run <dir>. It reads each file once, authenticates and cross-checks the pair with the same checks as environment-serve, checks the bundle name, then prepares the state under that name as the bundle's server will at startup to predict what the bundle serves (replay when the state is unavailable), copies the bytes it authenticated, refuses to write into a directory that exists and is not empty, and never overwrites a file.

rea environment-export manifest.json --evidence capture.json ./grafana-example --json

The folder holds a README.md with the bundle's provenance, an env folder envs/<name>/ with a Dockerfile that installs this exact rea-agents version and serves the copied manifest.json and evidence.json (written with mode 0600 on POSIX; Windows retains inherited ACLs) with environment-serve (from the state by default), a Python verifier under artifacts/check_<name>/ that checks the served tool count and one served answer, and the smoke task tasks/smoke.json. --package-tarball copies a packed rea-agents tarball into the env folder and installs it instead of the registry package, which is how the hosted lane proves a checkout rather than a release. --name replaces the manifest's kebab-case name as the env folder and env id; a device name Windows reserves (con, nul, com1 and the like) is refused. The command prints one JSON document listing the written files with their sizes, the pinned package source, the served tool_count, and state in the shape of the serve command's stopped document. See agent environments for the folder layout and what the smoke task checks.

Compare an environment with its application

rea environment-compare <manifest.json> --evidence <capture.json> --probe <probe.json> [--probe <probe.json> ...] compares the environment the pair serves with probe captures of the application it came from. Each probe is capture Evidence of one call sequence recorded against the application after a reset; the environment's state is reset before each probe, every request to the application's origin is answered as the served environment answers it, and the answer is compared with the application's after ids are mapped and clocks and generated values are normalised. The command reads files only and makes no network call. It prints the report and exits 0, or prints a structured invalid_request error and exits 1 for the same pair refusals as environment-serve, a probe that is not capture Evidence, or a browser probe captured without response bodies, or without the request bodies its writes need. See agent environments for the report.

rea environment-compare manifest.json --evidence capture.json --probe probe.json --json

Report version and runtime

rea --version prints the package version. Add an output format to get the version with the runtime and platform context that a support request needs:

Version reports do not initialize analysis providers. Invalid global settings or output options still report their usual errors.

rea --version --json
{
  "name": "rea-agents",
  "version": "6.7.0",
  "runtime": { "id": "node", "version": "24.22.1" },
  "platform": "linux",
  "architecture": "x64",
  "supported_runtime": {
    "range": "^22.23.4 || ^24.22.1 || >=26.12.1",
    "satisfied": true
  }
}
Field Meaning
name, version Published package name and version; version matches plain --version.
runtime.id node or bun.
runtime.version Version of that runtime.
runtime.node_compatibility_version Bun only: the Node.js version it reports compatibility with.
platform, architecture Node.js process.platform and process.arch, such as linux and x64.
supported_runtime.range Supported Node.js range.
supported_runtime.satisfied Whether this runtime is supported, judged as rea doctor judges it; Bun by its Node.js compatibility version.

The field names are stable. The report contains no paths, environment values, user or host names, and it starts no provider and reads no target. --format selects any CLI output format, such as --format yaml. JSON follows the usual rule: indented on a terminal, compact when piped or redirected. --help still takes precedence. With other output controls, --version keeps its existing behavior: valid controls such as --filter-output or --full-output print the plain version, and invalid combinations report the usual output-flag error, such as UNSUPPORTED_OUTPUT_COMBINATION for --json with --token-limit. Use rea doctor for provider and host readiness.

Output and exit status

rea mcp doctor --json checks production MCP startup and reports child logs in diagnostics. It drains stderr while retaining at most its first 64 KiB of raw bytes as text, omitting a final UTF-8 code point if it crosses that byte limit. stderr_bytes counts all observed bytes, including omitted output; stderr_truncated indicates that output exceeded the retention limit. The same diagnostics appear inside the report when --full-output is selected. Log truncation alone does not change the diagnostic health or exit status.

The default terminal format is TOON. Use --json when saving results for a JSON consumer. Valued output flags (--format, --filter-output, --token-limit, --token-offset) accept --flag value or --flag=value; a missing value fails with MISSING_OUTPUT_VALUE before the command runs. --json is indented on a terminal and compact when piped or redirected, which keeps large results smaller for agents and scripts; pipe through jq . for indented files. Output selection and formatting do not change operation status.

--format md escapes backslashes and pipes in table headers and cells, and renders cell line breaks as <br>. These are presentation changes; retained Evidence and JSON output keep the original values. Table widths are measured iteratively, so an admitted row page is not limited by the JavaScript function argument count.

--filter-output selects fields from successful command data. Classified failures retain their complete typed diagnostic projection even when the selector matches a field such as code or message, or names a missing field. --full-output controls whether the outer {ok, error, meta} envelope is included. Selected own JSON members, including __proto__, remain ordinary output data.

Sibling array slices that select different fields are combined by original row index and emitted in source order, regardless of selector order. Selecting a whole parent row keeps that row intact and takes precedence over narrower fields selected from the same row. For example, rows[0,2].name,rows[1,3].version combines both fields for overlapping rows, while rows[0,2],rows[1,3].version retains rows 0 and 1 whole.

For cutter-command, --json-output requests command-specific JSON from Cutter when available. This is separate from --format json, which selects the CLI result representation; the global --json flag selects that same CLI representation.

Cutter still accepts deprecated --json=true and --json=false compatibility values. When both forms are present, --json-output takes precedence in either argument order. Bare --json retains its global meaning of selecting JSON CLI output formatting.

Status Meaning
0 The operation completed. Its result may include partial evidence, warnings or unresolved questions.
1 The operation could not complete. Structured output identifies invalid input, permissions, cancellation, timeouts or another failure when available.
128 + N Signal-derived status. An unhandled signal may have ended the process, with the shell or runtime preserving the conventional status; a command may instead have handled the signal, waited for its operation and cleanup to settle, and assigned the same status (130 for SIGINT, 143 for SIGTERM). In the handled case, it may also have printed a structured cancelled result.

rea mcp --http is long-running and prints no structured result. It exits 130 on SIGINT or 143 on SIGTERM after closing the listener, the session and its providers, and 1 when that cleanup fails.

rea environment-serve is also long-running: it serves until SIGINT or SIGTERM, closes the listener, then prints one structured {"status":"stopped", …} document naming the URL, environment and tool count and exits 130 or 143 through the shared cancellation handler below. Refusals before binding (unreadable files, non-Evidence JSON, capture Evidence in a format other than HAR, a manifest or state whose parent is not the supplied evidence, an unbindable port) print a structured error and exit 1, as does a listener that fails after binding. rea environment-export is one-shot: it prints the written files and exits 0, or prints a structured invalid_request error and exits 1 for the same pair refusals, a non-empty or file-occupied directory, a missing package tarball or a name that is not a kebab-case label or is a Windows device name, writing nothing in each case. A write that fails after the first file (a permission, disk-space or pathname-length failure on a later path) propagates as the host's failure, naming its cause and, when it failed on one bundle file or the package tarball, that file. A failure while syncing the finished folder names only its cause. Either way the partial folder stays in place for inspection; remove it before retrying, since the next attempt refuses the non-empty directory.

A cancelled result does not by itself determine the exit status; it depends on the command's signal handling. Commands routed through the shared withCommandCancellation handler in the CLI set status 130 for SIGINT or 143 for SIGTERM after their operation settles. Current source registrations use that handler for process capture and comparison (capture-process, compare-process-captures), JavaScript application analysis (analyze when it selects the JavaScript lane, and analyze-javascript-application), selected browser, web and Electron commands (including analyze-web-bundle, observe-web-execution, capture-browser-scenario and capture-electron-scenario), and the platform and provider command families for Android/ADB, Apktool/JEB/Flutter, firmware, PCAP and signal analysis, WASM/EVM, Go/Rust and binary diagnostics, Frida instrumentation, the Cutter command, objdump, Rizin and GDB, and the agent environment server (environment-serve). In these paths, a returned structured cancelled result can be printed before the wrapper assigns the signal-derived status. This describes the current source routing; it is not a claim that every command or provider runtime has been independently exercised.

Commands with --evidence_output select their delivered view, then publish the complete Evidence bundle atomically. Cancellation before publication leaves no new file. A publication that has committed can win a later cancellation; the cancelled result then keeps the written path and byte count under details.diagnostics.evidence_bundle. If staging cleanup stays incomplete after commit, the cleanup_incomplete error reports the same file as details.published_path and details.bytes.

When the reader of piped output closes early, as rea ... | head does, the CLI stops writing, prints no error and exits 141 (128 + 13, the status of a SIGPIPE-terminated writer). The operation itself may have completed; only its output was declined.

inspect-artifact also returns a structured cancelled result, but its direct analysis cancellation path does not set a signal-derived exit status, so it exits 1. Setup has its own contract: cancellation exits 0. Treat the structured result and process status as separate signals when scripting cancellation.

setup --dry-run returns planned and exits 0; a cancelled setup also exits 0. Setup returns 1 for needs_confirmation or needs_human. doctor returns 1 when required checks in its selected readiness scope fail; unavailable optional providers remain informational for unrelated tasks.

Enable pipefail in a supporting shell so a downstream formatter preserves REA's failure status:

set -o pipefail
rea inspect-artifact ./app.asar --json | jq . > inspection.json