Skip to content

Releases: MxIris-Reverse-Engineering/RuntimeViewer

RuntimeViewer v2.1.0-beta.5

06 Jun 17:51

Choose a tag to compare

Pre-release

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:

  1. _loadImageForBackgroundIndexing short-circuits already-loaded
    images.
    The BFS routinely visits the peer's own main executable,
    which dlopen refuses to re-open by definition; on iOS Simulator it
    also hits system images whose canonical path differs from dyld's
    runtime form due to DYLD_ROOT_PATH rewriting. Checking imageList
    first avoids the spurious DyldOpenError at source.

  2. canOpenImage / rpaths / dependencies now 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-side DyldUtilities.machOImage lookup, so BFS got stuck at
    the root and batches only ever indexed the main executable instead
    of its full dependency closure. (Wire-format addition:
    RuntimeDependencyEntry replaces the tuple-typed dependencies
    return value at the dispatch seam — tuples aren't Codable. 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. sendRequest used to hold sendSemaphore
    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, pendingRequests keys 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 — nonce is optional and absent values fall back to
    identifier-keyed routing.
  • Decode-failure arm swallows silently. The receive catch arm
    previously echoed a bare RuntimeNetworkRequestError with no
    identifier when 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. Configurable depth (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

  • UIFoundation 0.10.0 → 0.10.2 (visual-effect opt-out hook,
    safe-area anchoring on macOS 11+).
  • RxAppKit 0.4.0 → 0.5.0 (drives rx.itemSelected off
    selectionDidChangeNotification so keyboard / type-select
    selection events surface alongside clicks — already relied on by
    the type-select navigation debounce shipped in beta.4).
  • swift-dependencies 1.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:

  • @Mutex macro dropped from RuntimeMessageChannel; back to the
    hand-rolled Mutex<T> + withLock form 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

04 Jun 16:20

Choose a tag to compare

Pre-release

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.onMessageReceived through 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-time Package.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

03 Jun 16:43

Choose a tag to compare

Pre-release

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:

  1. 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.

  2. RuntimeNetworkConnection.observeIncomingMessages spawned 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.
  • RuntimeNetworkConnection now matches RuntimeLocalSocketConnection and
    RuntimeDirectTCPConnection: the callback only does a non-blocking
    yield into an unbounded AsyncStream<Data>, and one long-lived consumer
    task drains it. Early messages yielded before the consumer task reaches
    for await are 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 on deinit instead of leaking it for the full process
    lifetime.
  • SharedCache management APIcontains / remove / removeAll
    let holders explicitly tear down cache entries on disposal.
  • Internal refactors that fold GenericContext initialisers onto the
    unified ReadingContext path, 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

03 Jun 01:50

Choose a tag to compare

Pre-release

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_MAX limit, 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 a LoadingButton placeholder — the UI no longer hangs while the
    list is being assembled.
  • Lazy cell view models for the type picker. A new
    DifferentiableBox wrapper 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 runtimeObjectsInImage response 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-service library — XPC connection, peer lifecycle, and
    daemon entry all delegate to the library now, leaving this repo with a
    thin set of Runtime-specific adapters.
  • RuntimeViewerCore was split: parsing lives in dedicated indexers, the
    relationships engine has its own resolver, and RuntimeSwiftSection was
    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 with Runtime*, dropped @unchecked Sendable).

RuntimeViewer v2.1.0-beta.1

17 May 17:05

Choose a tag to compare

Pre-release

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> where Foo is 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

01 May 14:50
455ba88

Choose a tag to compare

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.sendRequest releases 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.shArchiveScript.sh; gains --update-packages
  • Runtime-engine ownership moved into the RuntimeViewerApplication package; mirror reconcile/dedup logic extracted into RuntimeEngineMirrorRegistry with unit tests
  • RuntimeViewerCore / RuntimeViewerPackages gain USING_LOCAL_DEPENDENCIES env 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

24 Apr 07:04

Choose a tag to compare

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

24 Apr 05:13

Choose a tag to compare

Pre-release

v2.0.0-RC.6

One-time manual install required

This is the first RuntimeViewer build to include Sparkle-based auto-updates.
Users on v2.0.0-RC.3 or 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 unified ReleaseScript.sh

Bug Fixes

  • Fix a receive-loop deadlock caused by conflicting no-response handler sentinels
  • Serialize RuntimeClientConnection mutable state with @Mutex to eliminate a concurrent-access race

Dependencies

  • Bump MachOKit to 0.49.100 and drop the private DyldPrivate import

v2.0.0-RC.3

03 Mar 05:52

Choose a tag to compare

v2.0.0-RC.3 Pre-release
Pre-release

v2.0.0-RC.2

01 Mar 16:08

Choose a tag to compare

v2.0.0-RC.2 Pre-release
Pre-release

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_addresses tool 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