0.9.0
Address notes (new)
Every address in the disassembly pane now grows a chat-style note
surface. Right-click a row and pick Notes & AI… (or click the
gutter breadcrumb when a thread already exists) to open a popover
with the address's threads; the user can leave plain notes or ask
the LLM with the disassembly and pdc around the anchor seeded
into the system prompt.
- Threads are anchored to an address with a chain of
user / assistant / system messages. Notes carry an editor chain,
individual messages carry a single immutable author. The gutter
renders a breadcrumb per address with active threads. - Replies stream token-by-token in both frontends; an in-flight
reply can be cancelled. - Each AI roundtrip runs against the session's ambient mission,
billing token usage and recording the call as aMissionAction
so the chain is reviewable from the mission view. - Threads can be renamed (pencil button in the popover header) and
individual user messages can be edited or deleted inline, with
destructive actions confirmed. - Notes sync via collaboration (
AddressNoteOp: upsert / remove
plus message append / edit / remove) and persist across detach,
so threads remain readable and writable when the session isn't
live.
LLM-backed reverse-engineering tools (new)
Four typed mission tools layered on radare2 + the mission's LLM:
suggest_function_name, suggest_function_signature,
suggest_local_names, and find_vulnerabilities. Suggestions are
proposals — the agent applies them via r2_cmd if it wants.
- New
r2_cmdmission tool runs ad-hoc radare2 commands against
the session's r2 context (output capped by
max_output_chars). - Address-note threads run through the shared mission tool catalog
so they have the same surface area as the standalone agent. rename_insightis now LLM-callable and auto-runs in the mission
loop; the agent dedupes resolver matches sharing an address and
picks friendly names for AI-installed hooks.- Sessions created by the agent notify the sidebar so they appear
immediately instead of waiting for the next refresh.
Detach-resilient inspection (new)
Disassembly, backtraces, and address notes now keep working when
the process is gone.
- Per-session module analysis (executable ranges + known
functions, keyed by module name + LC_UUID) is persisted, so
on-demand analysis runs once per binary and rebases cleanly on
reattach. - Basic blocks per analyzed function are persisted alongside, used
to answerenclosingFunctionoffline. - Memory pages are cached and survive detach: module pages are
keyed by module UUID + offset so cached bytes survive ASLR;
anonymous (JIT / heap) pages key on a process identity and are
purged on every fresh attach. Engine.symbolDisplayreturns a richerSymbolDisplay(overlay,
source, raw, primary) and persists every live symbolicate result
intomodule_symbol. Offline rendering falls through to that
table, then toenclosingFunctionfrom the persisted block
ranges, then tomodule+offset. Trace block annotation flows
through the same path so detached traces still get names.- Backtrace popovers and "Open Insight" buttons resolve through a
newEngine.anchor(sessionID:, address:)that falls back to
lastKnownModuleswhen the node is gone. - Insight detail refresh actions: Reread Bytes drops the
pages overlapping the visible range; Reanalyze Module drops
the module's analysis and pages, re-running r2 on next access.
Insight naming
Address insights gain a real identity.
userTitlereplaces the auto-derived title; display name falls
back to<parent.title>+0x<delta>, thensub_<offset>at
function starts, thenmodule+offset.- A
parentInsightIDlink is maintained automatically: new
insights link to the enclosing function-start insight, and
adopt their siblings when they themselves are a function start.
FreshModuleAnalysisruns reparent existing insights when new
function starts appear. - Sidebar context menu Rename… and the
rename_insighttool
both route throughEngine.renameInsight, which broadcasts via
updateInsightand pushes the name into r2 as a flag (plus
afnat function starts). - Dependents (tracer hooks, address notes, sidebar rows) are
notified on rename so labels refresh live.
Collaboration
The on-disk RE state is now part of the lab snapshot:
- New
SessionOps:updateProcessInfo,updateModuleAnalysis,
updateInsight,updateModuleSymbols, plus a side-channel
publish-memory-page/+fetch-memory-pagerequest. The
driver write-throughs every page it fetches; non-drivers pull
on miss and persist locally. Late-joiner snapshots ingest the
wholemodule_symboltable, all module analyses, and process
info. - Process instances carry a deterministic identity (per-OS, with a
Process.mainModule+ pid fallback) stashed on
ProcessSession.processInfo, used to key the anon-page cache.
Action Queue (new)
A global Action Queue surfaces in the toolbar as a popover. It
auto-closes when empty.
Project persistence
GTK opens each document into a fresh working copy and exports a
VACUUM INTO snapshot to the user-facing path on save and on
close. Because the engine never moves, hooks stay attached across
Save As. The window-close handler holds the GApplication
while the snapshot and shutdown drain; Engine.shutdown flushes
EventLog and awaits chained event-store writes so events.log
is durable.
The event log moves from a directory of segments to a single
events.log file; EventStore takes a file URL directly.
Tracer
- Hook switcher in the tracer config view on both frontends, with
the menu factored into a shared builder on GTK. - New mission tools:
read_tracer_hook/edit_tracer_hookand
read_custom_instrument_file/edit_custom_instrument_file
returnline_countso the agent can target line ranges
instead of rewriting whole files. - Add All in the API picker coalesces into one binding write —
the JSON-roundtripping config binding had been dropping
intermediate state so only the last hook landed.
MCP
tool_call_idis wrapped into a JSON envelope alongside the
tool result body. MCP clients don't surface_metato the
model, so findings could never be grounded; the unused field
is gone.
UI / UX
- Arm actions are hidden on sessions that don't go through the arm flow.
- Editor avatars (the stack used by notebook entries) are reused
on the mission list / detail and in the address-note popover
header and message rows. - JS inspector tightens up: nested expanders default to collapsed
via a depth counter; children show in chunks of 5; rows align on
first text baseline. The previous SwiftUI recursion bug from a
bareplatformLinkButtonStyle()is fixed. - HookPack and custom-instrument detail panes are scrollable so
widgets past the visible area can be reached. - Browse for program path action on the local-device new
session sheet. - Live mission text is restored on view re-entry.
- New mission rows highlight when they first appear (GTK).
isDarkModeis replaced by aLumaCore.Appearanceenum
threaded through the disassembler and theme watchers; CFG views
usethemeAppearanceto avoid clashing withNSView's
inheritedappearance.- iOS editor background now goes through a platform helper so it
picks upUIColor.secondarySystemBackground. - GTK: detached banner stays hidden while attaching; stdio toggle
tracks state; execution section content inset; New Session
toolbar button restyled to match the SwiftUI target glyph.
Internal
Authorextracted into a shared model;REPLCell,Mission,
and address notes all attribute through it.- Note threads run through the shared LLM tool catalog.
- LLM prompts share a code-style preamble.
runCommand/decompilereturnR2CommandResultso callers
see r2's log entries;findFunctionStartrunsaaponce per
session before giving up; disasm bounds at function end via
$FB/$FEandpDJwhen available.- Disassembler is decoupled from
ProcessNodeviaMemoryReader
andModuleIntrospectorprotocols, with a per-session page
store routing r2 reads. - GTK ContextMenu now goes through SwiftGtk bindings instead of
raw C; destructive confirmations switched fromAdw.AlertDialog
to inline popovers so they no longer steal focus from their
parent.
Dependencies
- SwiftyR2 rolled forward to pick up the analysis surfaces the
new RE tools depend on.