P0: Explicit save & durable persistence for the decompiler CLI#204
Merged
Conversation
Agents renamed/retyped through DecLib used to vanish on stop/reload because
IDA closed its database with close_database(False). This adds first-class
persistence so edits become durable artifacts across backends.
- New DecompilerInterface.save(path=None) + persist_on_close control.
- IDA: idc.save_database via compat.save_database; reopen an existing
.i64/.idb directly (no re-analysis, no headless overwrite-prompt hang).
- Ghidra: GhidraProject.save(program); close honors persist_on_close so
--discard actually reverts.
- Binary Ninja: writes/snapshots a .bndb (best-effort).
- angr: in-memory, raises NotImplementedError.
- CLI: `decompiler save [--path]` and `decompiler stop --save|--discard`.
- CLI: NotImplementedError now surfaces as a clean "not implemented"
message with a distinct exit code (2) instead of a generic error.
- Client proxies save()/set_persist_on_close() and reconstructs
NotImplementedError across the wire.
- Reopen-and-verify tests for IDA + Ghidra; unsupported-path test for angr.
- SKILL.md / docs / CLI docstring updated.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HfZHdprXg38re1XyKxzGg5
This was referenced Jul 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Work done through DecLib (renames, retypes, comments) could disappear after
stop+ reload — IDA closed its database withclose_database(False), discarding everything. This is the P0 persistence gap. This PR adds a first-class, cross-backend save so agents can produce durable.i64/ Ghidra-project /.bndbartifacts.New capabilities
decompiler save [--path]— flush the backend's analysis to disk.decompiler stop --save | --discard— persist before shutdown, or explicitly drop unsaved edits (mutually exclusive).DecompilerInterface.save()+persist_on_closecontrol, implemented per backend:idc.save_database; reopens an existing.i64/.idbdirectly on reload (no re-analysis, no headless overwrite-prompt hang)GhidraProject.save(program); teardown honorspersist_on_closeso--discardtruly reverts.bndb(best-effort)NotImplementedErrorNotImplementedErrornow crosses the client/server wire intact and the CLI printsnot implemented: …with a distinct exit code2, so scripts can tell "unsupported on this backend" apart from a real failure.Example
Tests
Backend-parametrized
tests/test_decompiler_cli.py:test_save_command_persists_rename_across_reload— save → stop → reload, rename intact (IDA + Ghidra, both pass).test_stop_save_persists_rename_across_reload—stop --savepath (IDA + Ghidra pass).test_save_unsupported_on_inmemory_backend— angrsaveexits 2.test_stop_save_and_discard_are_mutually_exclusive.Run with the
declibenv against IDA 9.2 (idalib), Ghidra 12.1 (pyghidra), and angr. Binary Ninja code paths are implemented but not exercised here (module not installed in the test env).First PR in a series closing the IDALib-parity gaps; subsequent PRs (comments, globals/signatures, typed reads, search, repair, patching, scripting) stack on this branch.
🤖 Generated with Claude Code
https://claude.ai/code/session_01HfZHdprXg38re1XyKxzGg5