feat(interface): show resume hint on user-initiated exit

When the user shuts down a run (Ctrl+C in CLI, Ctrl+Q / quit dialog
in TUI, or an uncaught exception during the scan), print a Rich
panel telling them the exact command to pick up where they left off:

    strix --run-name <run_name>

The panel only appears when ``strix_runs/<run_name>/bus.json``
exists — i.e. the scan registered at least the root agent and has
snapshot state worth resuming from. Suppressed when:

  * No run-name was assigned (Ctrl+C before sandbox bring-up).
  * The run dir doesn't exist or has no bus.json yet.

Implementation:

  * ``strix/interface/utils.py`` gains ``format_resume_hint(run_name)
    -> Panel | None``.
  * ``cli.py`` calls it in the SIGINT/SIGTERM/SIGHUP handler before
    ``sys.exit(1)``, and in the ``except Exception`` arm before the
    re-raise.
  * ``tui.py:run_tui`` calls it in a ``finally`` after
    ``app.run_async()`` so the hint lands on the real terminal once
    Textual has restored it (whether the user pressed Ctrl+Q,
    confirmed the quit dialog, or the run completed naturally).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
0xallam
2026-04-26 00:34:44 -07:00
co-authored by Claude Opus 4.7
parent d538acf66b
commit 1c4cb4dc8a
3 changed files with 57 additions and 2 deletions
+9
View File
@@ -21,6 +21,7 @@ from strix.telemetry.tracer import Tracer, set_global_tracer
from .utils import (
build_live_stats_text,
format_resume_hint,
format_vulnerability_report,
)
@@ -139,6 +140,10 @@ async def run_cli(args: Any) -> None: # noqa: PLR0915
def signal_handler(_signum: int, _frame: Any) -> None:
tracer.cleanup()
hint = format_resume_hint(args.run_name)
if hint is not None:
console.print()
console.print(hint)
sys.exit(1)
atexit.register(cleanup_on_exit)
@@ -212,6 +217,10 @@ async def run_cli(args: Any) -> None: # noqa: PLR0915
except Exception as e:
console.print(f"[bold red]Error during penetration test:[/] {e}")
hint = format_resume_hint(args.run_name)
if hint is not None:
console.print()
console.print(hint)
raise
if tracer.final_scan_result: