Releases: MxIris-Reverse-Engineering/RuntimeViewer
RuntimeViewer v2.1.0-beta.5
v2.1.0-beta.5
Fifth public preview of the 2.1 line. Clears the
v2.1.0-beta.4 known-issue on remote-Server background
indexing, ships the new Always Index list (re-rolled from the build
that beta.4 had to revert), and reorganizes the Background Indexing
settings into a master switch plus two independently toggleable sub-modes.
This is a beta build — only clients that opted in via
Settings → Updates → Include pre-release versions receive it.
Bug Fixes
Remote-Server background indexing no longer stalls image loading
beta.4 documented the ping-pong: when the Server side of a remote engine
(iOS Simulator, iPad / iPhone over Bonjour, etc.) had background indexing
on, LoadImageForBackgroundIndexingRequest dlopen'd the peer's own
main executable and returned DyldOpenError. The error payload carried
no identifier, the peer envelope-decoded it as keyNotFound, and both
sides ping-ponged on the shared sendSemaphore — image-list pushes,
indexing progress, and on-demand object requests all starved.
Two coordinated fixes ship in this build:
-
_loadImageForBackgroundIndexingshort-circuits already-loaded
images. The BFS routinely visits the peer's own main executable,
whichdlopenrefuses to re-open by definition; on iOS Simulator it
also hits system images whose canonical path differs from dyld's
runtime form due toDYLD_ROOT_PATHrewriting. CheckingimageList
first avoids the spuriousDyldOpenErrorat source. -
canOpenImage/rpaths/dependenciesnow dispatch instead of
reading the client process's dyld directly. The protocol's "pure
local check" assumption only ever worked on the local engine; remote
engines were silently returning empty dependency lists from the
client-sideDyldUtilities.machOImagelookup, so BFS got stuck at
the root and batches only ever indexed the main executable instead
of its full dependency closure. (Wire-format addition:
RuntimeDependencyEntryreplaces the tuple-typed dependencies
return value at the dispatch seam — tuples aren'tCodable. The
manager-facing API is unchanged.)
Communication-layer hardening: per-round-trip nonce + swallow decode failures
Adjacent to the indexing fix, the request/response channel itself got
two structural fixes that prevent any future peer-handler failure from
amplifying into a ping-pong:
- Per-round-trip nonce.
sendRequestused to holdsendSemaphore
from wait-to-resume, so a slow peer handler (e.g. 20 s of section
parsing during background indexing) monopolized the channel and
blocked every other in-flight send at the local outbox. Each round
trip now stamps a UUID nonce,pendingRequestskeys by nonce, and
the semaphore releases as soon as the write returns; concurrent
sends wait on responses in parallel and identifier-keyed collisions
on the routing table are impossible. Wire format is backward
compatible —nonceis optional and absent values fall back to
identifier-keyed routing. - Decode-failure arm swallows silently. The receive catch arm
previously echoed a bareRuntimeNetworkRequestErrorwith no
identifierwhen envelope decode failed, which is what fed the
beta.4 ping-pong. It now splits into two arms: decode failures
swallow silently; handler failures echo via the same nonce-keyed
envelope used by successful responses, so the peer routes the error
back to its matching pending entry instead of re-echoing.
New Features
Always Index list
The user-configurable Always Index list shipping in beta.5 is the
re-rolled version of the feature that beta.4 had to back out at archive
time. Each row pins a single image — either a full path (starting with
/) or a file-name shorthand matched against the loaded image list by
last-path-component — and the background indexer runs that image
through a batch every time a document opens, the runtime engine
changes, or the list itself changes.
Toggle Follow Dependencies on a row to also walk the image's
dependency closure using the same depth as Heuristic Discovery;
otherwise only the image itself is indexed.
Entries that don't match any loaded image are silently skipped and
re-tried on the next fullReload — useful for remote engines whose
imageList populates asynchronously after documentDidOpen.
Background Indexing: master switch + two sub-modes
The Background Indexing settings have been reorganized from a single
toggle into a master switch plus two independently toggleable sub-modes:
- Master switch (
Enable Background Indexing) — overall on/off.
When off, neither sub-mode runs. - Heuristic Discovery — main-executable BFS at document open and
engine swap. Configurabledepth(1...5) lives under this sub-mode. - Always Index — the new list described above.
Max Concurrent Tasks is shared between sub-modes. Each toggle reacts
independently: turning Heuristic Discovery off mid-run cancels only
heuristic batches; Always Index batches keep running, and vice
versa. Flipping the master switch off cancels everything.
Background Indexing popover: grouped by reason
Each section (ACTIVE / HISTORY) now groups its batches by reason
category — Heuristic Discovery / Always Index / Manual — under a
collapsible header instead of rendering one flat list of batches.
Always-index groups flatten one level (entry → item) so single-image
rows show the user-supplied identifier directly.
Improvements
RuntimeMessageChannel stack-overflow guards rolled back
The snapshot-before-loop and AsyncStream<Data> consumer fixes from
beta.3's bec9f4b were a workaround for the @Mutex _modify
coroutine pinning that already got removed in beta.4
(0fdca62 fix(communication): revert @Mutex macro back to manual Mutex<T>).
With the real trigger gone, the guards were dead weight and the
strictly serial drain was incidentally compounding latency when a peer
echoed handler errors at high rate. Reverted in aa8ba43.
RuntimeEngine.imageNodes exposed as nonisolated
imageNodes is now a nonisolated getter backed by the underlying
CurrentValueSubject; mutations still go through the actor-isolated
setImageNodes(_:). Synchronous call sites no longer need an await
hop, which is what gates the Export Multiple Images menu item on
imageNodes.count >= 2 inside validateMenuItem (which runs on the
main thread and can't suspend).
Dependencies
UIFoundation0.10.0 → 0.10.2 (visual-effect opt-out hook,
safe-area anchoring on macOS 11+).RxAppKit0.4.0 → 0.5.0 (drivesrx.itemSelectedoff
selectionDidChangeNotificationso keyboard / type-select
selection events surface alongside clicks — already relied on by
the type-select navigation debounce shipped in beta.4).swift-dependencies1.12.0 → 1.13.0 (declares the trait set the
resolved graph enables; required by release-channel resolves under
USING_LOCAL_DEPENDENCIES=0).
Carried Over From beta.4
All changes from v2.1.0-beta.4 ship unchanged:
@Mutexmacro dropped fromRuntimeMessageChannel; back to the
hand-rolledMutex<T>+withLockform from beta.1.
And from v2.1.0-beta.3 the MachOSwiftSection
0.12.0-beta.3 bump and the wider remote-pin refresh.
And from v2.1.0-beta.2 the Inspector
Relationships tab, Batch Export, selection history, and the
underlying communication-layer hardening.
RuntimeViewer v2.1.0-beta.4
v2.1.0-beta.4
Fourth public preview of the 2.1 line. Re-rolls the Bonjour crash fix from
beta.3: beta.3's release binary still overflowed the
dispatch-queue worker stack inside AsyncStream.yield. Everything else
carries over from beta.3 unchanged.
This is a beta build — only clients that opted in via
Settings → Updates → Include pre-release versions receive it.
Bug Fixes
Bonjour-connection crash regression vs. beta.3
beta.3 shipped two coordinated fixes for the original v2.1.0-beta.2
EXC_BAD_ACCESS on a Bonjour batched receive:
- snapshot
RuntimeMessageChannel's@Mutex-backed properties into
locals before the hot loop, and - bridge
RuntimeNetworkConnection.onMessageReceivedthrough an
AsyncStream<Data>drained by one long-lived consumer task.
In debug builds the combination was enough. In release, the binary still
crashed in AsyncStream._Storage.yield with a stack-guard fault — the
crash backtrace showed two RuntimeViewer offsets (0xe88a0 / 0x6c33c)
recursing tightly inside a single connection.receive callback on the
com.RuntimeViewer.RuntimeViewerCommunication.RuntimeNetworkConnection
queue. The @Mutex macro's _modify coroutine accessor still pinned
coroutine context on the caller's frame across iterations even with the
snapshot in place, just less of it.
This build drops the @Mutex macro from RuntimeMessageChannel entirely
and goes back to the hand-rolled Mutex<T> + withLock form that shipped
in v2.1.0-beta.1 (which never crashed on this path). withLock is a plain
synchronous function — no coroutine, no caller-frame pinning, the stack
unwinds cleanly between iterations.
The buffered-stream bridge from beta.3 stays in place: callback only does
a non-blocking yield and the long-lived consumer task drains
handleReceivedMessage off the dispatch-queue stack.
Carried Over From beta.3
All changes from v2.1.0-beta.3 ship unchanged:
- MachOSwiftSection 0.12.0-beta.3 bump (opaque-type symbolic-ref fix +
SymbolIndexStore self-cleanup + SharedCache management API). - Remote-pin refresh across
RuntimeViewerCore/RuntimeViewerPackages
to the current latest tag of each non-pinned dependency. - ArchiveScript: force-checkout in the detached-HEAD branch so the
appcast PR step no longer aborts on archive-timePackage.resolved
drift.
And from v2.1.0-beta.2 the Inspector Relationships
tab, Batch Export, selection history, and the underlying
communication-layer hardening.
RuntimeViewer v2.1.0-beta.3
v2.1.0-beta.3
Third public preview of the 2.1 line. Stability focus on top of
beta.2: one critical crash fix in the Bonjour-based
network connection, plus a MachOSwiftSection bump that picks up an
SwiftUI-related opaque-type parsing fix. Everything else carries over
from beta.2 unchanged.
This is a beta build — only clients that opted in via
Settings → Updates → Include pre-release versions receive it.
Bug Fixes
Crash on Bonjour-routed peers under batched receives
Inspecting an iOS / visionOS / Apple TV target over Bonjour, or pushing a
batch-export through a Bonjour connection, could crash with
EXC_BAD_ACCESS once a single NWConnection.receive carried more than a
few dozen small frames (heartbeats, acks, or export chunks). The crash hit
the connection's dispatch-queue worker thread with a 13_000+ frame stack
overflow.
Two compounding factors fed the overflow on this code path:
-
RuntimeMessageChannel's message-dispatch loop accessed two
@Mutex-decorated properties (receivedDataContinuation,
onMessageReceived) on every iteration. The macro-generated_modify
coroutine accessor pinned ~280 bytes of coroutine context on the caller's
frame per access and the frames did not unwind between iterations. -
RuntimeNetworkConnection.observeIncomingMessagesspawned a fresh
Task { await handleReceivedMessage(data) }for each message inside that
same loop, adding another ~10 frames per iteration on top of (1).
The fix:
- The dispatch loop now snapshots both properties into locals before the hot
loop, so each iteration only touches local variables and the_modify
coroutine frames no longer accumulate. RuntimeNetworkConnectionnow matchesRuntimeLocalSocketConnectionand
RuntimeDirectTCPConnection: the callback only does a non-blocking
yieldinto an unboundedAsyncStream<Data>, and one long-lived consumer
task drains it. Early messages yielded before the consumer task reaches
for awaitare buffered, preserving FIFO across the entire receive burst.
Regression tests cover a 10k-message burst delivered from a dispatch queue
plus a disabled reproducer that replays the pre-fix per-message-Task shape
for manual verification.
Cross-image opaque-type parsing crash (via MachOSwiftSection 0.12.0-beta.3)
Bumps MachOSwiftSection to 0.12.0-beta.3, which fixes a crash when an
indexed image references a Swift opaque-return type whose underlying
descriptor lives in a sibling loaded image — e.g. SwiftUI body code that
resolves View.searchFieldStyle(_:) against DVTUserInterfaceKit. Before
the bump, the MachOContext<MachOImage> decoder treated the symbolic
reference offset as in-image and walked off into __PAGEZERO. The decoder
now mirrors the Swift runtime and resolves the descriptor through the
in-process pointer scheme, making cross-image references transparent.
The same MachOSwiftSection bump also brings:
- SymbolIndexStore self-cleanup — short-lived indexers now release their
cache entry ondeinitinstead of leaking it for the full process
lifetime. SharedCachemanagement API —contains/remove/removeAll
let holders explicitly tear down cache entries on disposal.- Internal refactors that fold
GenericContextinitialisers onto the
unifiedReadingContextpath, fixing a latent negative-size bug in the
legacy in-process decoder.
Carried Over From beta.2
All features from v2.1.0-beta.2 ship unchanged: the
Inspector Relationships tab, the Batch Export flow under File →
Export Multiple Images…, selection history in the toolbar, and the
underlying communication-layer hardening.
RuntimeViewer v2.1.0-beta.2
v2.1.0-beta.2
Second public preview of the 2.1 line. Headline additions: a new
Relationships tab in the Inspector, a Batch Export flow from the File
menu, and selection history in the toolbar. Plus a stack of performance
and stability fixes carried over from beta.1.
This is a beta build — only clients that opted in via
Settings → Updates → Include pre-release versions receive it.
New Features
Inspector → Relationships
A new Relationships tab sits between Hierarchy and Specialization and
shows where a type is referenced across the binaries you have loaded.
- Surfaces inbound references (who uses this type) and outbound references
(what this type depends on), drawn from a dedicated relationships engine. - Works across binaries: if the indexed images include the consumers of a
type, they show up regardless of which dylib defines it. - The list lays out cleanly even when a type has no relationships — an empty
state explains why instead of showing a blank tab.
Batch Export
Export the interfaces of multiple images in one pass without opening each
document individually.
- New File → Export Multiple Images… entry walks you through image
selection, format selection, and destination directory in a single sheet. - Per-language format choices (Objective-C
.h, Swift surface, etc.) are
remembered across runs, so the next export starts where you left off. - The completion summary now uses stat cards to show how many files
succeeded, failed, or were skipped, and lists each failure individually so
you can re-run only what broke. - Export file names are clamped below the APFS
NAME_MAXlimit, so long
Swift-mangled names no longer produce errors mid-batch.
Selection History in the Toolbar
The toolbar now drives back / forward navigation off a true selection
history cursor, the way Xcode and Finder do.
- Picking a sidebar item, drilling into a type, and switching between
Hierarchy / Relationships / Specialization tabs all push onto the same
stack. - The buttons enable / disable based on what's actually in the history, so
you never end up clicking back into nothing. - The active inspector tab is preserved when you move between selections, so
jumping back into a type returns you to the panel you were last reading.
Sidebar: smarter expansion
- Single-clicking a non-leaf row now expands it (matching how the rest of
macOS treats outline rows). - A new setting caps how deep a double-click expands an entire subtree, so
you can preview a framework without exploding hundreds of children.
Performance
- Type-picker prep moved off the main thread. When you open the
Specialization sheet for a generic with a wide constraint, the candidate
list (10k+ entries in common cases) is now built on a background queue
with aLoadingButtonplaceholder — the UI no longer hangs while the
list is being assembled. - Lazy cell view models for the type picker. A new
DifferentiableBoxwrapper defers per-row view-model construction until
the row is actually rendered, cutting time-to-first-frame on large
candidate lists by roughly an order of magnitude. - macOS 26 navbar push cost cut. Pushing the inspector when the user
selects a new sidebar row reuses the existing view controllers instead of
rebuilding them, removing a visible flash that appeared on macOS 26.
Bug Fixes
- The Inspector no longer races against
reloadData()when you click
through the sidebar rapidly — in-flight reloads are now cancelled before
the next one starts. - Indexing skips weak-load dylibs that are shadowed by the dyld shared
cache, so they no longer show up as "missing" entries. - Injected servers now resolve their main binary path through the dyld
registry, which fixes the inspector failing to load for some injection
targets. - XPC peer activation runs after the modifier installs its handlers,
closing a small race window that could drop the first request on a fresh
connection. - Inspector specialization rows can no longer be selected by accident — the
parameter table now refuses row selection the way the rest of the
inspector does. - Decoding the
runtimeObjectsInImageresponse now uses the right request
type, so the inspector populates correctly for some injection scenarios
that previously returned an empty list.
Under the Hood
- The RuntimeViewer ↔ helper transport was rebuilt on top of the upstream
swift-helper-servicelibrary — XPC connection, peer lifecycle, and
daemon entry all delegate to the library now, leaving this repo with a
thin set of Runtime-specific adapters. RuntimeViewerCorewas split: parsing lives in dedicated indexers, the
relationships engine has its own resolver, andRuntimeSwiftSectionwas
carved into focused extensions instead of one growing file.- Document navigation is now state-driven from
DocumentState.selectionStack
rather than ad-hoc coordinator calls, which is what unlocks the toolbar
history behaviour above. - The communication layer was tightened (sealed
VoidResponse, prefixed
shared transport types withRuntime*, dropped@unchecked Sendable).
RuntimeViewer v2.1.0-beta.1
v2.1.0-beta.1
First public preview of the 2.1 line. Two big features ship together:
Generic Type Specialization and Background Indexing, plus a built-in
iOS Simulator runtime installer.
This is a beta build — only clients that opted in via
Settings → Updates → Include pre-release versions receive it.
New Features
Generic Type Specialization
Inspect Swift generic types with the concrete arguments you care about.
- Pick any Swift generic from the sidebar and a new Specialize… sheet
lets you fill in its type parameters. The Inspector then renders the fully
specialized interface alongside the original unspecialized form. - The picker handles nested generics — when an argument is itself generic
(e.g.Result<Foo, Bar>whereFoois generic), you can drill in and fill
those parameters in the same sheet. - Type definitions can come from a different binary than the generic itself,
so you can specialize types in framework A using a model from framework
B loaded in the same document. - Invalid combinations are caught up-front with a clear error instead of
silently producing garbage.
Background Indexing
Stop waiting for the sidebar to populate. Once a document opens, RuntimeViewer
walks the dylib dependency graph and starts indexing related binaries in the
background, so by the time you click into them they are ready to inspect.
- A new toolbar progress popover shows what is currently indexing, lets you
cancel any individual batch, and keeps a history of recent runs. - A new Settings → Indexing page controls how aggressively background
indexing runs (or turns it off entirely). - Selecting a binary that is still in the queue immediately bumps it to the
front. - Background work runs at a low priority so it never makes the main UI
stutter.
iOS Simulator Runtime Installer
A new built-in installer downloads and installs missing iOS Simulator runtime
images directly from the app — no more chasing them down through Xcode.
Improvements
- Toolbar no longer shows an empty overflow chevron on macOS 15 when its only
items are hidden. - Refreshed the Mirror menu icon (the previous SF Symbol was deprecated).
Bug Fixes
- Fix the Inspector failing to load for re-bound apps (some Catalyst /
Simulator binaries). - Background-indexing the same binary more than once is now a true no-op
instead of duplicating work. - Closing a document while background indexing was in flight no longer leaks
the runtime engine. - The progress popover stays in sync when the document switches its mirror
source mid-session.
RuntimeViewer v2.0.1
v2.0.1
Stability patch focused on multi-device runtime mirroring and the
underlying message-channel transport.
Improvements
AWDL / Bonjour transport
- Per-request timeouts on every mirrored-engine RPC so a stalled remote no longer pins a sidebar entry indefinitely
- Heartbeat-based liveness probes for AWDL-routed peers — the sidebar reflects reality much faster when a peer drops off
- Tolerate transient AWDL congestion: brief failures no longer fire a spurious "disconnected" notification
Engine mirroring
- Forwarded mirror engines are cleared when the leaf peer they advertise actually disconnects
- Mirrors duplicating a direct local route are suppressed so a peer doesn't show up twice when reached two ways
Bug Fixes
RuntimeMessageChannel.sendRequestreleases its send semaphore on every exit path (previous code leaked a slot whenever the request threw)- The timeout task is cancelled the moment a response arrives, so it can't fire later against a re-used identifier
- Pending requests are drained with an error when the underlying transport closes — callers no longer hang on a dead channel
Internal
- Release tooling renamed
ReleaseScript.sh→ArchiveScript.sh; gains--update-packages - Runtime-engine ownership moved into the
RuntimeViewerApplicationpackage; mirror reconcile/dedup logic extracted intoRuntimeEngineMirrorRegistrywith unit tests RuntimeViewerCore/RuntimeViewerPackagesgainUSING_LOCAL_DEPENDENCIESenv switch
Dependencies
- Bump AssociatedObject 0.15, combine-schedulers 1.2, FrameworkToolbox 0.5.2, Rearrange 2.1.1, swift-asn1 1.7, swift-certificates 1.19.1, swift-dyld-private 1.2
- Add RunningApplicationKit + RxAppKit pins
RuntimeViewer v2.0.0
v2.0.0
Important
If you run into device connection issues (e.g., iOS devices or other macOS peers not being discovered), completely uninstall any previous version (App Cleaner is recommended) before retrying, and make sure every device is running the latest version.
Runtime Viewer v2.0.0 is a ground-up rewrite of the runtime inspection engine
with first-class Swift support, MCP integration for LLM clients, multi-device
inspection over Bonjour, and built-in auto-updates.
Manual install required for this release
v2.0.0 is the first RuntimeViewer build with Sparkle auto-updates. If you
are on v1.x or any earlier v2.x beta / RC, download and install this release
manually — future releases will arrive through Check for Updates….
Highlights
- Swift interface support — generate Swift type interfaces, memory layouts, and enum layouts from Mach-O binaries
- MCP integration — let LLM clients (e.g., Claude) inspect runtime information via the Model Context Protocol
- Bonjour multi-device — discover and connect to iOS / macOS peers on the local network; remote engines mirror into your toolbar
- Code injection reconnection — injected processes survive app restarts
- arm64e code injection — inject into arm64e system apps with helper service support
- Export interface wizard — Xcode-style multi-step export for ObjC and Swift interfaces
- Auto-update — opt-in beta channel, EdDSA-signed archives, feed served from GitHub Pages
What's new
Swift interface support
Swift type interfaces with memory layout, enum layout, VTable offsets, and
a generic-type indicator icon. Swift-specific generation options control
concurrency annotations, access control, and more. Powered by
MachOSwiftSection.
Faster, more accurate ObjC engine
ClassDumpRuntime is replaced by
MachOObjCSection.
Better performance, better memory behavior, with category dumping.
MCP integration (macOS 15+)
- Built-in MCP bridge server with automatic port discovery
- Tools to list classes / protocols, fetch interfaces, look up member addresses, and load/unload images
- Status indicator and connection popover in the main toolbar
- MCP settings page with port configuration and one-click client config copy
Bonjour & multi-device
- Discover and connect to iOS and macOS peers on the local network
- Remote runtime engines show up in the toolbar alongside local ones, grouped by host
- Device name, icon, and simulator flag carried over Bonjour metadata
- Automatic retry on transient failures
- iOS real-device support including local-network permission handling
Code injection
- Reconnect automatically to previously injected processes on app restart
- arm64e targets supported (main app stays arm64, helper and server frameworks compile as arm64e)
- Inspect sandboxed apps via local TCP sockets
Export & transformers
- New Xcode-style wizard for exporting ObjC / Swift interfaces to files — handles C++ template filenames and special characters
- Pluggable runtime interface transformers: C type replacement, Swift type layout, enum layout, VTable offsets, and member addresses
- Customizable token-template presets, reorderable in Settings
Auto-update (Sparkle)
- Check for Updates… directly below About
- Updates settings page with check interval, manual check, and an opt-in beta channel
- Every archive verified with an EdDSA signature
- Appcast feed served from GitHub Pages
Filters, bookmarks, and quality-of-life
- Fuzzy filter for classes and protocols
- Drag-to-reorder bookmarks
- Determinate progress bar in the sidebar with phase descriptions ("indexing Swift types", "loading ObjC classes", …)
- Debug → Export Logs for one-click OSLog export
- System notifications on connect / disconnect
- Jump-to-definition icon in the interface viewer
- IMP addresses shown in ObjC interface output
Platform requirements
- Main app: macOS 15+
- MCP features: macOS 15+
- iOS variant: iOS 18+
- Runtime inspection library: macOS 10.15+, iOS 13+, Mac Catalyst 13+, watchOS 6+, tvOS 13+, visionOS 1+
Migration from v1.x
- Helper Service — migrated to
SMAppService. Reinstall from Settings → Helper Service after upgrading. - Bookmarks — storage moved to Application Support; a one-time migration runs on first launch.
- MCP — new feature. Point your LLM client at the MCP server path shown in Settings → MCP.
RuntimeViewer v2.0.0-RC.6
v2.0.0-RC.6
One-time manual install required
This is the first RuntimeViewer build to include Sparkle-based auto-updates.
Users onv2.0.0-RC.3or any earlier v2.x beta/RC must download and install
this release manually — there is no auto-update path from a Sparkle-less
build. Every release after RC.6 will be delivered through the in-app
update flow.
New Features
Auto-Update (Sparkle)
- Integrated Sparkle for secure, in-app automatic updates
- Check for Updates… menu item directly below About
- New Updates settings page with "Check now", automatic-check toggle, check interval (hourly / daily / weekly), and opt-in pre-release (beta) channel
- EdDSA signature verification on every downloaded archive
- Appcast feed served from GitHub Pages (
docs/appcast.xml); subsequent releases update the feed automatically through the unifiedReleaseScript.sh
Bug Fixes
- Fix a receive-loop deadlock caused by conflicting no-response handler sentinels
- Serialize
RuntimeClientConnectionmutable state with@Mutexto eliminate a concurrent-access race
Dependencies
- Bump MachOKit to
0.49.100and drop the privateDyldPrivateimport
v2.0.0-RC.3
v2.0.0-RC.2
v2.0.0-RC.2
Bug fixes and improvements since v2.0.0-RC.1.
Improvements
App Behavior
- The app no longer quits when the last window is closed — you can reopen documents from the menu or Dock icon
- Window toolbar now uses the unified style for a cleaner look
Export
- Fixed the "Export Interface" menu item not being clickable
- The export menu is now automatically disabled when no image is selected, preventing accidental clicks
- Improved exported file naming for more intuitive output
Sidebar & Search
- Fixed the case-insensitive toggle not taking effect when filtering
- Fixed filter results not refreshing immediately after switching search modes
- Improved search debouncing to reduce unnecessary refreshes while typing
Interface Viewer
- ObjC method interface output now includes IMP address comments for easier function location
- ObjC property getter/setter interface output now includes IMP address comments
- Significantly improved syntax highlighting rendering performance for smoother browsing of large interfaces
MCP Integration
- Added
get_member_addressestool for querying Swift function and computed property memory addresses - Improved descriptions for all MCP tools so LLM clients can understand and use them more accurately
- Improved MCP Bridge async communication design for better stability
- Added "Copy MCP Server Path" menu item for easier LLM client configuration
Bug Fixes
- Fixed a crash in the export wizard caused by a lost router reference under certain conditions
- Fixed redundant work when loading the same image multiple times
- Fixed the window title not correctly reflecting the currently selected image name
- Fixed a potential crash when the case-insensitive search button was accessed before the view was fully loaded