Skip to content

Terminal Recorder

The terminal recorder captures an already-running tmux-backed agent session for later parser and lifecycle testing. It lives under tools/terminal_record and is implemented by houmao.terminal_record.

For maintainer-oriented design notes and change guidance, see the Terminal Recorder Developer Guide.

Use the repo-managed Python environment when invoking it:

pixi run python -m tools.terminal_record start --mode active --target-session HOUMAO-gpu --tool codex

Modes

active

  • creates a recorder-owned tmux attach path
  • records asciinema input frames with --capture-input
  • publishes recorder state back into the target tmux session so repo-managed send-keys calls can append structured managed-input events
  • starts with input_capture_level=authoritative_managed
  • degrades to managed_only if the run becomes tainted, for example when extra tmux clients attach to the target session

passive

  • observes a live tmux session without becoming the required input path
  • records the visual session and pane snapshots only
  • marks the run as input_capture_level=output_only

Commands

Start an active run against a single-pane session:

pixi run python -m tools.terminal_record start --mode active --target-session HOUMAO-gpu --tool codex

Start a passive run against a specific pane:

pixi run python -m tools.terminal_record start --mode passive --target-session HOUMAO-gpu --target-pane %1 --tool codex

Inspect a run:

pixi run python -m tools.terminal_record status --run-root tmp/terminal_record/20260319-120000-HOUMAO-gpu

Stop a run:

pixi run python -m tools.terminal_record stop --run-root tmp/terminal_record/20260319-120000-HOUMAO-gpu

Analyze recorded pane snapshots:

pixi run python -m tools.terminal_record analyze --run-root tmp/terminal_record/20260319-120000-HOUMAO-gpu

Persist a label for a recorded checkpoint:

pixi run python -m tools.terminal_record add-label \
  --run-root tmp/terminal_record/20260319-120000-HOUMAO-gpu \
  --label-id trust-prompt-blocked \
  --scenario-id trust-prompt-recovery \
  --sample-id s000021 \
  --diagnostics-availability available \
  --turn-phase unknown \
  --last-turn-source none

Artifact Contract

Each run writes one recorder-owned root under tmp/terminal_record/<run-id>/ unless --run-root overrides it.

Important artifacts:

  • manifest.json: recorder mode, tmux target, capture authority, taint metadata, attach command, and timing metadata
  • live_state.json: long-running controller status used by status and stop
  • session.cast: operator-facing asciinema cast produced via the repo-owned pixi run asciinema task backed by extern/orphan/bin/asciinema-x86_64-unknown-linux-gnu
  • pane_snapshots.ndjson: exact tmux pane samples captured with tmux capture-pane; this is the authoritative replay surface, and each output_text entry can feed the standalone shared TUI tracker directly
  • input_events.ndjson: normalized input events when the selected mode provides managed input capture
  • parser_observed.ndjson: parser-facing observations generated by analyze
  • state_observed.ndjson: official tracked-state observations generated by analyze, including diagnostics posture, surface, turn, and last_turn fields, with any retained readiness/completion fields treated as debug-only
  • labels.json: structured operator labels for recorded samples or sample ranges

The recorder keeps session.cast for human review, but automated replay and testing should consume pane_snapshots.ndjson.

Managed send-keys Integration

The existing send-keys path remains the runtime delivery mechanism for mixed tmux control input. When an active recorder is live for the same tmux-backed session, the backend's send_input_ex() method appends a structured managed_send_keys event to input_events.ndjson after successful tmux delivery.

This integration is additive. Recorder logging failures do not block the underlying control-input delivery.