Skip to main content

Session Recording

Capture a terminal session as a timestamped stream of events, replay it inside TermFlow, or export it to JSON, plain text, HTML, or an asciinema cast for sharing and archiving.

Session recording is driven by TermFlow's local Recordings API and paired with an in-app playback viewer. A recording captures the terminal's output (and, optionally, your keystrokes and resize events) as events tagged with a millisecond offset from when recording started, so playback reproduces the session at its original pace — or faster, or slower.

An honest note: Session recording is part of TermFlow 0.1.0's early-access release. The Recordings API, all four export formats, and the playback viewer described on this page are implemented and working today; expect the capture and export pipeline to keep evolving as TermFlow moves past pre-release.

How it works

Each recording is a self-contained document: an ordered list of events, plus metadata (title, detected shell, and the terminal's initial size in columns and rows). Recordings persist as JSON files on disk — one file per recording — inside TermFlow's application data folder, so they survive restarts and are listed back to you the next time you open the app.

Auth

Like every TermFlow endpoint, the recordings API is unauthenticated on localhost because it is bound to 127.0.0.1. If you turn on "Expose on local network," the routes require the bearer token from Settings → Connections. See Local API and auth.

Recording a terminal

Start a recording against a terminal id. The terminal must already exist; TermFlow reads its current size to seed the recording's metadata.

POST /api/recordings/start
Content-Type: application/json

{
"terminal_id": "term-1a2b",
"options": {
"include_output": true,
"include_input": true,
"include_resize": true,
"compression": "gzip",
"auto_stop": false
}
}

A successful start returns 201 Created:

{ "recordingId": "b3f1…", "terminalId": "term-1a2b", "status": "recording" }

The options object is optional — omit it to accept the defaults below.

OptionTypeDefaultEffect
include_outputbooltrueCapture terminal output
include_inputbooltrueCapture your keystrokes
include_resizebooltrueCapture resize events
compressionstring"gzip""none" or "gzip"; recorded in the file's metadata
auto_stopboolfalseAuto-stop flag (leave off)

Stop the recording by its recording id (not the terminal id). TermFlow stamps the end time, writes the file to disk, and reports the final size and event count:

POST /api/recordings/stop/b3f1…
{ "recordingId": "b3f1…", "status": "stopped", "size": 20480, "eventCount": 512 }
One recording per terminal

A terminal has at most one active recording at a time. Use GET /api/recordings/status/:terminalId to check whether a terminal is currently recording, and GET /api/recordings/active to list every recording in progress.

Exporting a recording

Export converts a saved recording into a portable file. Send the desired format to the export endpoint; TermFlow responds with the file as a download (Content-Disposition: attachment).

POST /api/recordings/b3f1…/export
Content-Type: application/json

{ "format": "asciinema" }
# Export a recording to an asciinema cast file
curl -X POST http://127.0.0.1:42031/api/recordings/b3f1…/export \
-H "Content-Type: application/json" \
-d '{"format":"asciinema"}' \
-o session.cast
formatContent typeWhat you get
jsonapplication/jsonThe complete recording — every event (output, input, resize), all timestamps, and metadata. Lossless; ideal for re-importing or programmatic analysis.
texttext/plainA plain-text dump of the output events, preceded by a short header comment (id, terminal, start/end, event count). Raw bytes, so ANSI escape sequences are preserved as-is.
htmltext/htmlA standalone, dark-themed HTML page containing the captured output — open it in any browser, no server required.
asciinemaapplication/jsonAn asciinema v2 cast (a header line plus one JSON line per output event), downloaded as a .cast file. Play it with the asciinema player or upload it to asciinema.org.

The in-app recordings list offers one-click Export as JSON / Text / HTML; the asciinema format is available through the API. An unrecognized format value returns 400 Bad Request.

Playing back a recording

Open a saved recording in the playback viewer to replay it in a read-only terminal. The viewer renders the recorded output at its original timing (input is disabled during playback), with transport controls and a scrubber.

┌─ Recording: my-session ─────────────────────────  [✕] ┐
│ Terminal: term-1a2b Duration: 84s Events: 512 │
├───────────────────────────────────────────────────────┤
│ │
│ (the recorded session replays here, read-only) │
│ │
├───────────────────────────────────────────────────────┤
│ ⏮ ▶ / ⏸ ⏹ ⏭ 0:12 ────●────────── 1:24 │
│ Speed [ 1.0x ▾ ] ☐ Loop │
├───────────────────────────────────────────────────────┤
│ Space Play/Pause Esc Stop Shift+←/→ Step Home/End│
└───────────────────────────────────────────────────────┘

Playback speed is adjustable from 0.25× to 4× (0.25, 0.5, 1, 1.5, 2, 3, 4), and a Loop toggle restarts the recording when it reaches the end. Click or drag the progress bar to seek to any point.

Keyboard shortcuts

KeyAction
SpacePlay / pause
EscStop (reset to the start)
Shift+Step to the previous recorded event
Shift+Step to the next recorded event
HomeJump to the start
EndJump to the end

Automate with the Recordings API

Everything above — start, stop, list, inspect, export, delete — is exposed as plain HTTP, so you can script recording around builds, test runs, or agent sessions.

Method & pathPurpose
POST /api/recordings/startBegin recording a terminal
POST /api/recordings/stop/:idStop and save a recording
GET /api/recordingsList saved recordings
GET /api/recordings/:idFetch a full recording (JSON)
GET /api/recordings/:id/infoFetch metadata only (duration, counts)
DELETE /api/recordings/:idDelete a recording
POST /api/recordings/:id/exportExport as json / text / html / asciinema
GET /api/recordings/status/:terminalIdWhether a terminal is recording
GET /api/recordings/activeList active recording ids

Full request and response schemas live in the Recordings API reference.

Next steps