Recordings
When someone gets an interactive shell on a protected host, Churchill captures the session live as a timestamped terminal recording. The cast is sealed with a SHA-256 content hash, uploaded to the control plane, and anchored to an event on the evidence chain. The Recordings page is where you find those captures and replay them, entirely in the browser. A count of sealed casts appears next to the page title, with a + when more pages are available to load.
Finding a recording
Section titled “Finding a recording”Two text filters narrow the list: one matches on the host, the other on the Unix user the shell ran as. The host box takes either a hostname or a host ID; a name is resolved against the fleet before the query goes out. Next to them, range chips limit the list to the last 24h, 7d, or 30d of sessions. The default is all. If you arrive from a host’s detail page, the host filter is prefilled for you. See Host detail.
The list loads the most recent sessions first. Select Load more at the bottom of the table to page further back.
When the filtered host’s capture posture is tampered, an alert strip appears above the table: the host, “session recording tampered” with the reported reason, and “recordings below may be incomplete”. Treat the list as partial until the tampering is investigated. See Capture posture.
Columns
Section titled “Columns”Each row is one recorded session. Selecting a row loads it into the replay player below the table. The columns are:
| Column | Meaning |
|---|---|
| Host | The host the session ran on, by name where the fleet has one and by host ID otherwise. Hover it to read the host ID either way. |
| User | The Unix user the shell ran as. |
| TTY | The terminal device of the session. Shown as a dash when not reported. |
| Remote | Where the session connected from. Shown as a dash when unknown. |
| Started | How long ago the session started. Hover for the wall-clock time. |
| Duration | How long the session lasted. Shows open while the session is still running and its cast has not been sealed yet. |
| Size | The size of the cast. |
| Masked | How many input spans were redacted at capture, highlighted when greater than zero. See Redaction below. |
| Evidence seq | The sequence number of the evidence event this recording is anchored to. It is a link: selecting it opens that event on the Evidence page. A recording with no anchor shows a dash. |
Replaying a session
Section titled “Replaying a session”Select a row and the cast downloads into the TTY session replay card. Playback happens entirely in the browser. The console redraws the session’s terminal output frame by frame, on the recording’s original timeline.
The player’s header shows the host, user@remote, the shell, the terminal type and size (for example 80×24), a count of redacted spans when there are any, and the format label asciinema · cast v2. The card header shows the cast’s sealed SHA-256. Select it to copy the full hash.
The transport bar gives you:
- Restart and Skip to end: jump to either end of the recording.
- Back 5s and Forward 5s: step through in small hops.
- Play/Pause: pressing play at the end restarts from the beginning.
- A draggable scrubber: drag anywhere on the track to seek. Elapsed and total time show beside it.
- A speed button: cycles playback speed through 1× → 1.5× → 2× → 4× → 0.5×.
A recording that was cut off mid-upload still plays. Everything captured before the cut is valid, and playback ends there.
Redaction
Section titled “Redaction”Input typed while terminal echo is off, the normal password path, is masked at capture. The recorder never writes those bytes, so a masked span in the cast is purely a time range. The secret itself does not exist in the recording.
In the player, masked spans render as tinted segments on the scrubber. Hover one to see its time range. While the playhead is inside a span, an input redacted pill appears in the player header. The Masked column in the table counts these spans per recording.
Every replay is audited
Section titled “Every replay is audited”Fetching a cast for replay appends an entry to the operator audit chain, recording who replayed which session, before any recording data is served. If that append fails, the recording is withheld. This is by design: you can always watch a recording without an approval step, but you can never watch one without leaving a trail. See Audit log.
Recordings and evidence
Section titled “Recordings and evidence”The link runs in both directions. The Evidence seq column here opens the anchoring event on the Evidence page. On the evidence side, an event with a sealed recording offers Replay session, which returns here with that cast loaded in the player.
Empty and error states
Section titled “Empty and error states”An empty list means different things depending on whether the filtered host is recording at all, and the page says which. With a host filter set, the message follows the host’s capture posture:
- Not recording, arm failed, or tampered (shown in the alert color): “This host is not recording sessions (…). An empty list here is a coverage gap, not a quiet host.”
- Retired: “This host is retired. Session recording was torn down when it was decommissioned, so nothing new is captured — casts sealed before then are still listed and replayable.”
- Recording: “No recordings match. This host is recording — no interactive session has been sealed in this window.”
- Never reported: “No recordings match, and this host has never reported a session-recording arming result — whether it records is unknown.”
Without a host filter: “No recordings match. Recordings appear once a session’s cast is sealed and uploaded; filter by host_id to see whether that host is recording at all.”
Whether a host records at all is decided during enrollment: chrlctl asks, and a host that declined stays unarmed. See Running chrlctl.
If the console cannot fetch the list from the control plane, the page reports Recording list unavailable with a short reason. If a selected cast cannot be fetched, including the fail-closed case where the replay could not be recorded on the audit chain, the player reports Cast unavailable instead of playing. Treat either as temporary and retry once the control plane connection recovers.