You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add the ability to save decoded traffic to a file and open/replay a saved file later, from both the CLI and the TUI. This turns a live capture into a durable, re-viewable transcript.
Core decision: file format
This is the key design point. The decoder currently formats everything into a String before it reaches the consumer — emit() produces [HH:MM:SS.fff] [F→B] Kind: text and App.events: Vec<String> only ever sees the rendered string (src/decode.rs:145, src/decode.rs:82-97). So there is no structured event type today. Pick one (recommend structured):
Plain transcript (simple) — write the rendered lines verbatim, like tee/a log. Round-trips as text and is grep-able, but an opened file is display-only (cannot be re-filtered or re-rendered rich, because structure is gone).
Either way, define the format explicitly. If plain transcript is chosen as the default, structured can be a --save-format jsonl option.
Saving
CLI: a flag such as --save <file> (and/or --tee <file> to keep stdout/--tui running while also writing). Writing should go straight to disk from the live stream so nothing is lost to the in-memory history cap (HISTORY_CAP, --conn-history), independent of the capped buffer.
TUI: a slash command (:w <file> / :save <file>) from the command bar (TUI command bar: interactive command/input line in the bottom section #14) to dump the current session to a file. Decide whether it saves the full session or only the in-memory buffer (full session preferred if continuously buffered to disk).
Opening / replaying
CLI: a flag such as --open <file> / --replay <file> / --from-file <file> that makes tapgres read a saved file instead of capturing from pcap/mitm — i.e. a new "file source" alongside pcap and mitm. It feeds the same decoded-record stream into the TUI/stdout, so the renderer is unchanged. (Structured format required for this to be meaningful.)
TUI: a slash command (:o <file> / :open <file>) to load a file into the buffer, replacing or appending the current view.
Consider replay pacing (instant load vs. timed replay) — instant load is fine for v1.
Behaviour to define
What happens when opening a file that was saved with an unknown/older schema version (graceful warning + best effort, or refuse).
Whether opening a file replaces the live source or is session-only in the TUI.
Timestamps: preserve original capture timestamps on display, and/or show a "replay" indicator so a replayed session is distinguishable from a live one.
Out of scope
Remote save/load (e.g. to a URL or DB). Local files only.
If structured is chosen, a prerequisite sub-task is introducing a structured event type at the decoder boundary instead of formatting to String immediately (src/decode.rs:145-154); the existing Output::Line/Status enum (src/decode.rs:72-79) is the natural place to extend.
Goal
Add the ability to save decoded traffic to a file and open/replay a saved file later, from both the CLI and the TUI. This turns a live capture into a durable, re-viewable transcript.
Core decision: file format
This is the key design point. The decoder currently formats everything into a
Stringbefore it reaches the consumer —emit()produces[HH:MM:SS.fff] [F→B] Kind: textandApp.events: Vec<String>only ever sees the rendered string (src/decode.rs:145,src/decode.rs:82-97). So there is no structured event type today. Pick one (recommend structured):FieldSummarycolumns. A schema version field should be included since the shape will evolve. This lets an opened file be re-filtered (Display filter subsystem: filter decoded messages by client, type, and keyword #13) and re-rendered in rich mode (TUI rich display mode: type glyphs for descriptions and tables for data rows #15) exactly like a live session.tee/a log. Round-trips as text and is grep-able, but an opened file is display-only (cannot be re-filtered or re-rendered rich, because structure is gone).Either way, define the format explicitly. If plain transcript is chosen as the default, structured can be a
--save-format jsonloption.Saving
--save <file>(and/or--tee <file>to keep stdout/--tuirunning while also writing). Writing should go straight to disk from the live stream so nothing is lost to the in-memory history cap (HISTORY_CAP,--conn-history), independent of the capped buffer.:w <file>/:save <file>) from the command bar (TUI command bar: interactive command/input line in the bottom section #14) to dump the current session to a file. Decide whether it saves the full session or only the in-memory buffer (full session preferred if continuously buffered to disk).Opening / replaying
--open <file>/--replay <file>/--from-file <file>that makes tapgres read a saved file instead of capturing from pcap/mitm — i.e. a new "file source" alongsidepcapandmitm. It feeds the same decoded-record stream into the TUI/stdout, so the renderer is unchanged. (Structured format required for this to be meaningful.):o <file>/:open <file>) to load a file into the buffer, replacing or appending the current view.Behaviour to define
Out of scope
Notes
:w/:o), and TUI rich display mode: type glyphs for descriptions and tables for data rows #15 (rich re-render). A structured save format is what makes opened files participate in those features.Stringimmediately (src/decode.rs:145-154); the existingOutput::Line/Statusenum (src/decode.rs:72-79) is the natural place to extend.