Skip to content

feat: rat watch + resurrect + copy mode (combined) - #11

Merged
seamoss merged 3 commits into
devfrom
feat/watch-resurrect-copymode
Apr 24, 2026
Merged

seamoss merged 3 commits into
devfrom
feat/watch-resurrect-copymode

Conversation

@seamoss

@seamoss seamoss commented Apr 24, 2026

Copy link
Copy Markdown
Owner

Summary

Three features bundled because their individual PRs kept re-conflicting on the Cmd enum tail as peers merged. Three independent commits, each untouched from its original PR.

`rat watch` (c85392f)

Read-only passive observer. Attaches, replays, tails live output. Never sends input/detach/resize — the interactive attacher is untouched. Ctrl-C exits.

```sh
rat watch agent
rat watch agent | tee agent.out
```

`rat resurrect` (4689e86)

Spin up a fresh daemon whose event log is pre-seeded with an old session's PtyOutput, then attach. Visible scrollback is reconstructed; shell/env/cwd are fresh.

```sh
rat resurrect ~/.local/state/rat/.log
rat resurrect agent # via meta (works for dead sessions)
```

Adds `--seed-log` to `rat-daemon`; client routes via new `spawn_daemon_with_seed`.

Copy mode (d9497ce)

` [` enters an alt-screen scrollback viewer. Client-side 1 MiB ring buffer (`RAT_SCROLLBACK_BYTES` override). Live output held in a `pending` buffer during scroll; flushed on exit so the live view catches up.

Keys: `j`/`k` line, `Space`/`b` page, `g`/`G` top/bottom, `q`/`Esc` exit.

Closes

Test plan

  • cargo test + clippy -D warnings + fmt green locally
  • CI green
  • Smoke: each command exercised end-to-end against a live session

seamoss added 3 commits April 24, 2026 16:26
New `rat watch <id>` subcommand: attaches over the Unix socket and
replays + tails the session's PtyOutput to stdout, but never sends
ClientMsg::Input, Detach, or Resize. The interactive attacher (if
any) is completely untouched.

Implementation notes:
- Stays in cooked mode so the terminal's line discipline handles
  Ctrl-C → SIGINT cleanly, which the tokio signal task traps and
  uses to notify the read loop to exit.
- Reuses OutputFilter so keyboard-protocol enables from inner TUIs
  don't bleed into the watcher's terminal.
- Suppresses SessionEnded-based exit distinction with the shared
  `print_session_ended` banner so ending a session while watching
  is visually consistent with ending while attached.

Useful for pair/review ("peek without risk of typing"), CI-style
monitoring via `rat watch x > log`, or any tool that wants a live
byte stream from a session without the raw-mode contract of attach.
New `rat resurrect <source>` subcommand. Source is either a .log path
or a session name/id; for names, look up the meta file (works for
dead sessions too — metas outlive the process until clean shutdown
or `rat kill` sweeps them).

Plumbing:
- Daemon gets a new `--seed-log <path>` flag. Between SessionStarted
  and the PTY spawn, it reads the seed log's PtyOutput events and
  re-appends them to the fresh log, then writes a yellow separator
  marker so the user can see where the new shell begins. Non-visible
  events (ClientInput, Resized, SessionStarted/Ended) are dropped.
- Client gets `spawn_daemon_with_seed` as the plumbing core;
  `spawn_daemon` is now a thin `seed_log=None` shim over it, so the
  existing callers (`new`, `spawn_bare`, post-attach new-session) are
  unchanged.

What resurrect rebuilds: visible scrollback. What it doesn't: the
original process, env, cwd. This makes it genuinely useful after a
daemon crash or host reboot without pretending to be a full session
migration. Session migration is a separate roadmap item (durable
state across hosts).
New chord command `<prefix> [` enters an alt-screen scrollback viewer
while keeping the attached session alive in the background. Live
output accumulates in a client-side ring buffer (default 1 MiB,
overridable via `RAT_SCROLLBACK_BYTES`) and into a `pending` buffer
during copy mode; on exit the alt-screen pops off and `pending` is
flushed to stdout so the live view catches up.

Keys: `j`/`k` and arrow up/down for line-by-line scroll, `Space`/`b`
(or `Ctrl-F`/`Ctrl-B`, or PgDn/PgUp if the terminal sends them
contiguously) for page-by-page, `g`/`G` for top/bottom, `q`/`Esc` to
exit. Status bar shows the current visible-line / total-line counter.

Implementation notes:
- `InputFilter` gains `CMD_COPY = '['` and a non-terminal `copy_mode`
  flag in `FilterOutput` — same shape as the existing `help` flag.
- Output task routes filtered PtyOutput through `append_scrollback`
  (VecDeque with front-trim on overflow) and branches on an atomic
  `in_copy` flag: writes to stdout in normal mode, appends to the
  `pending` Vec while in copy mode.
- `run_copy_mode` uses `write_stdout_sync` helpers that lock +
  release `StdoutLock` per call. Holding the lock across `.await`
  breaks Send for the input task's spawned future; per-call locking
  sidesteps that without forcing the whole task into single-threaded.
- ANSI is stripped on render. Colour goes away in copy mode, but
  line-by-line navigation stays sane — raw cursor-movement sequences
  in the PTY byte stream would otherwise scramble the alt-screen
  rendering. Accepted trade-off; `rat grep` is the coloured search
  tool instead.

Banner + chord cheatsheet updated with `[=copy`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant