Skip to main content

asciinema-claude

Turn asciinema recordings of Claude Code sessions into the ANSI scrollback a user would see.

Install

pip install asciinema-claude

For development: uv sync, then uv run pytest -q. To record test fixtures, run scripts/install-asciinema.sh (installs asciinema 3.2.1 to tools/bin/asciinema).

Command line

asciinema-claude session.cast | less -R
asciinema-claude --no-color session.cast > session.txt
cat session.cast | asciinema-claude -

Options:

  • --clear-separator: mark each /clear with a separator line.
  • --no-color: write plain text, with no ANSI codes.
  • --follow: keep reading while the file grows (polls every 0.25 s). It waits for the file to exist. It stops on Ctrl-C, or at the exit event ("x") that asciinema 3 writes to v3 recordings. A v2 recording has no exit event, so stop it with Ctrl-C. A line is written only when it is final: when it scrolls off the top of the screen, or when the recording ends. A short session that fits on the screen shows nothing until then. At the end, the rest of the screen is written. Not allowed with -.
  • --version: print the version.

Exit codes: 0 on success, 1 for a file error (for example a missing file), 2 for a bad recording or bad usage, 130 for Ctrl-C (without --follow).

Library

One call:

from asciinema_claude import transcribe

text = transcribe("session.cast")                     # path, str, bytes or file object
text, info = transcribe("session.cast", return_info=True)
print(info.max_width, info.clears, info.reprints_removed, info.gaps)

Incremental, for a recording that is still growing:

from asciinema_claude import Transcriber

t = Transcriber(80, 24)           # the cast header resets the size
for chunk in chunks_of_cast_text:  # any split of the file is fine
    t.feed_raw(chunk)
    send(t.take_committed())       # final text, append it
    show_tail(t.tail())            # live tail, see below
send(t.finish())
info = t.info()                    # max_width, clears, reprints_removed, gaps

Output in take_committed() is final: append it and never change it. tail() is the live part: the screen rows that are not final yet, and lines held while a redraw is checked. It is replaced on each update, so do not append it. It can be taller than the screen (37 lines on a 30-row screen in the basic fixture).

Web app with xterm.js

Show the committed text in one terminal and the tail in a separate element, which you replace on each update:

// committed: new text from take_committed(); tail: tail(); width: info.max_width
const term = new Terminal({ cols: width, scrollback: 1000000 });  // default is 1000
term.write(committed);                  // append only; lines already end in \r\n
tailTerm.reset();                       // a second Terminal (or a <pre>) under it
tailTerm.write(tail);
  • Use info.max_width as the number of columns, so no line wraps. The width can grow while the recording grows: call term.resize(width, term.rows) when it does.
  • Set scrollback high. With the default of 1000 lines, xterm.js drops the start of a long transcript.
  • To use one terminal only, call term.reset() and write all committed text and then the tail on each update. This costs more for long transcripts.

A Transcriber cannot be pickled or stored between requests. A stateless backend can feed the whole recording again on each request (about 3 MB/s on a laptop). Do not call finish() while the recording grows. The committed text of a part of a recording is always the start of the committed text of the whole recording. So the client can send the length it already has, and the server returns only what is new and the tail:

def update(cast_text: str, offset: int) -> dict:
    t = Transcriber(80, 24)
    t.feed_raw(cast_text)
    committed = t.take_committed()
    return {"new": committed[offset:], "offset": len(committed), "tail": t.tail(),
            "width": t.info().max_width}

Claude Code modes

  • Inline mode (the default) and "tui": "fullscreen" mode (alternate screen) give the same kind of transcript. In fullscreen mode, the library copies each frame and finds how far the conversation moved. The rows that leave the top of the viewport are kept, as in inline mode.
  • Fullscreen mode, scrolling back: frames that show older rows are ignored. Claude Code marks these frames with a pill (Jump to bottom (ctrl+End) ↓, 1 new message (ctrl+End) ↓) and a sticky prompt at the top row. A frame that shows newer rows is copied, also while the user is scrolled back. Thus, if the user pages down, every row that was on the screen is kept once. The pill, the sticky prompt and the 1 new message divider are not kept.
  • Fullscreen mode, overlays: the slash menu, the @ file picker and other overlays above the input box are not kept. The conversation rows behind an overlay are kept.
  • Fullscreen mode, an external editor (ctrl+g): the editor's screen is not kept. Only frames that show Claude Code's input box or a permission prompt are copied.
  • A recording made with an idle-time limit (asciinema rec -i) gives the same transcript as one without it, for all limits down to 0 s.
  • After a resize, the repaint is matched with the history by paragraph. A table drawn again at another width (or as a Name: value list, on a narrow screen) is matched by its cells, so it is kept once. The size of the table does not matter.

Known limits

  • In fullscreen mode, Claude Code draws only the viewport. Rows that were never on the screen are not in the recording, so they cannot be in the transcript. Three cases cause this. The user jumps to the bottom after rows arrived while the view was scrolled back. More than one screen of rows arrives in one frame. An overlay hid the rows. At a jump, the transcript has this line where rows can be missing: ⋯ rows may be missing here: they were never on the screen. info.gaps counts these lines. Rows that only an overlay hid are not marked.
  • In fullscreen mode, if the viewport shows only repeated rows (for example a log of equal lines), the frames do not show how many rows left the top. The library takes the smallest number that agrees with the frames, and writes the gap line once for each such stretch. Some repeated rows can be missing. Other rows are not lost.
  • In fullscreen mode, an overlay above the input box is found by its form: indented rows with a blank row above them. An overlay of another form is kept as text. The library prefers this to the loss of a conversation row.
  • A table drawn again after a resize is matched by its cells. If the repaint starts so that only the end of one cell value is on the screen, that part is not matched, and it is kept twice. A duplicate is preferred over losing content.

Metadata

Release files for asciinema-claude 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for asciinema-claude 0.1.0
File Size Uploaded Provenance Actions
asciinema_claude-0.1.0.tar.gz 41.1 kB With provenance Details for asciinema_claude-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for asciinema-claude 0.1.0
File Interpreter ABI Platform Actions
asciinema_claude-0.1.0-py3-none-any.whl Python 3 none any Details for asciinema_claude-0.1.0-py3-none-any.whl

Total release size: 86.8 kB

Release files / asciinema_claude-0.1.0.tar.gz

Download URL asciinema_claude-0.1.0.tar.gz
Size 41.1 kB
Tags Source
SHA-256 checksum
How to use checksums
da8bc0685823f009cce0e5a5ad2e601fcf8935a461612b92ec4cac2d1cb63d35
BLAKE2b-256 checksum
How to use checksums
d4f5886f368784ece2e96b9b242bd66820e15bbc748f58b6f433dfac468102ac
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

Release files / asciinema_claude-0.1.0-py3-none-any.whl

Download URL asciinema_claude-0.1.0-py3-none-any.whl
Size 45.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2044e019d685153c5b78c18d446ec0dbd4a972c0290c443459c97e9cd9a60a5a
BLAKE2b-256 checksum
How to use checksums
5754377c6576fff483881f5a45e0763849f8866954b79781d0236d83c81e2d1d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

Security for asciinema-claude 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for asciinema_claude-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page