Skip to main content

termtosvg

Record a terminal session and get a standalone SVG animation you can drop into any web page.

No video encoding, no player to embed, no JavaScript. The output is a single vector file where the text is still text.

CI PyPI Python License

Example


Why SVG

The animation above is a 26-second session at 82ร—19 characters, in 50 KB. That is one file, and the properties that come with it are not available from a screen recording:

The text is real text Readers can select, copy and search the commands in your demo. Search engines index them.
Resolution independent Vector output stays crisp on a 4K display and at any zoom level. There is no "recorded at the wrong size" problem.
Themeable after the fact Colours are CSS classes, not baked pixels. Restyle a finished animation by editing its stylesheet.
Self-contained One .svg file. No player script, no external assets, no network requests. Works from file://.
Diff-friendly enough to commit Plain XML in your repository, embedded with a relative Markdown link.

Installation

termtosvg runs on Linux, macOS and the BSDs, and requires Python 3.10 or later.

python3 -m venv .venv
source .venv/bin/activate
pip install termtosvg-ng

Then run it as either termtosvg or python3 -m termtosvg.

[!IMPORTANT] The install name and the command name differ, on purpose. You install termtosvg-ng but you run termtosvg; the import package is termtosvg too.

The plain termtosvg name on PyPI belongs to the original author and last shipped 1.1.0 in January 2020. That release predates the removal of pkg_resources from setuptools, so on Python 3.12 and later it fails at import with ModuleNotFoundError: No module named 'pkg_resources' โ€” every command, --version included, dies immediately. termtosvg-ng is the same tool with that fixed.

Installing straight from source
pip install git+https://github.com/gaborini/termtosvg.git@develop
OS packages maintained by the community

These package the original termtosvg distribution, so they carry 1.1.0 and the caveat above applies to them.

OS Repository Command
Arch Linux extra/termtosvg pacman -S termtosvg
FreeBSD graphics/py-termtosvg
Gentoo media-gfx/termtosvg emerge media-gfx/termtosvg
macOS Homebrew brew install termtosvg
NixOS nixpkgs
OpenBSD graphics/termtosvg

Quick start

Start recording. You land in a subshell โ€” type as you normally would.

$ termtosvg
Recording started, enter "exit" command or Control-D to end

Leave the shell to finish:

$ exit
Recording ended, file is /tmp/termtosvg_exp5nsr4.svg

Open it in a browser to watch it, then embed it with a relative link:

![My demo](./demo.svg)

How it works

termtosvg separates capturing from drawing, which is what makes the output editable and reproducible:

                  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”                   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
   your shell โ”€โ”€โ–บ โ”‚    record    โ”‚ โ”€โ”€โ–บ .cast file โ”€โ”€โ–บ โ”‚    render    โ”‚ โ”€โ”€โ–บ .svg
                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   (asciicast v2)   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                            โ–ฒ                โ–ฒ
                                     hand-editable      SVG template
                                     timings & text     (theme + chrome)

Running termtosvg with no sub-command does both in one pass. Splitting them is useful because the intermediate .cast file is plain text: you can fix a typo, retime a pause, or re-render the same recording with a different theme without performing the session again.

termtosvg record demo.cast          # capture only
termtosvg render demo.cast out.svg  # draw, as often as you like

Because render reads the asciicast format (v1 and v2), it also renders recordings made with asciinema.

Command line reference

Three forms. The default records and renders in one go:

termtosvg [output_path] [-c COMMAND] [-D DELAY] [-g GEOMETRY] [-m MIN_DURATION]
          [-M MAX_DURATION] [-s] [-t TEMPLATE] [-v] [-h]

termtosvg record [output_path] [-c COMMAND] [-g GEOMETRY] [-v] [-h]

termtosvg render input_file [output_path] [-D DELAY] [-m MIN_DURATION]
                 [-M MAX_DURATION] [-s] [-t TEMPLATE] [-h]

Not every option applies to every form โ€” render takes its geometry from the recording, so it has no -g:

Option Default default form record render What it does
-c, --command COMMAND $SHELL, else sh โœ… โœ… โ€” Program to record, with arguments: -c 'ipython --pprint'.
-g, --screen-geometry COLSxROWS your terminal, else 80x24 โœ… โœ… โ€” Screen size to record at, e.g. 82x19.
-t, --template TEMPLATE powershell โœ… โ€” โœ… Built-in name (see below) or a path to your own template.
-m, --min-frame-duration MS 1 โœ… โ€” โœ… Merge frames shorter than this. Raise it to shrink output from commands that redraw constantly.
-M, --max-frame-duration MS noneยน โœ… โ€” โœ… Clamp long pauses, so thinking time does not stall the animation.
-D, --loop-delay MS 1000 โœ… โ€” โœ… Pause before the animation loops.
-s, --still-frames off โœ… โ€” โœ… Write one SVG per frame into a directory instead of one animation.
-v, --version โœ… โœ… โ€” Print the version.
-h, --help โœ… โœ… โœ… Print usage.

ยน Unless the recording's header carries idle_time_limit, which is then used.

Durations accept a bare integer or an ms suffix โ€” -m 17 and -m 17ms are the same. output_path is optional everywhere; a temporary file is generated when it is omitted (a directory, with --still-frames).

Templates

A template supplies the colour theme, the font, any window chrome, and how the animation is driven. Pass one by name with -t:

Template Look Animation
powershell (default) Windows PowerShell palette CSS
base16_default_dark Base16 default dark CSS
dracula Dracula CSS
gjm8 Understated dark, no chrome CSS
gjm8_single_loop gjm8, plays once instead of looping CSS
gjm8_play gjm8 with a play-icon drawn over the screen CSS
progress_bar Adds a progress bar tracking the animation CSS
putty PuTTY palette CSS
solarized_dark / solarized_light Solarized CSS
terminal_app macOS Terminal.app CSS
ubuntu Ubuntu terminal CSS
xterm xterm palette CSS
window_frame Adds a terminal window frame CSS
window_frame_powershell Window frame, PowerShell palette CSS
window_frame_js Window frame with play/pause buttons JavaScript

Embedding, and one caveat worth knowing

Fifteen of the sixteen templates animate through pure CSS, so they play when loaded as an ordinary image โ€” including from a Markdown ![...]() in a GitHub README.

window_frame_js is the exception: its play/pause controls need JavaScript, and browsers do not execute scripts inside an SVG loaded via <img>. Embed that one with <object> or <iframe>, or link to the file directly:

<object type="image/svg+xml" data="demo.svg"></object>

Writing your own template is documented in termtosvg-templates(5). The shipped templates under termtosvg/data/templates/ are the best starting point โ€” copy one and edit its palette.

Recipes

# Record a specific program instead of a shell
termtosvg -c 'ipython --pprint' demo.svg

# Pin the geometry so the animation is not tied to your window size
termtosvg -g 82x19 demo.svg

# Tame a chatty command: coalesce sub-17ms frames, cap pauses at 2s
termtosvg -m 17 -M 2000 demo.svg

# Re-theme an existing recording โ€” no need to perform it again
termtosvg render demo.cast dracula.svg -t dracula

# Render someone else's asciinema recording
termtosvg render downloaded.cast out.svg

# Still frames, e.g. to pick a thumbnail
termtosvg render demo.cast frames/ --still-frames

# Two seconds of breathing room between loops
termtosvg -D 2000 demo.svg

Compatibility

Python 3.10 โ€“ 3.14
Operating systems Linux, macOS, FreeBSD, OpenBSD (anything with a POSIX pty)
Not supported Windows, which has no pty module. WSL works.
Dependencies pyte (terminal emulation), lxml (SVG), wcwidth (wide-character widths)

Windows shells can still be recorded โ€” the powershell template exists for styling such recordings โ€” but termtosvg itself must run on a POSIX host.

Development

make install   # editable install with dev extras
make tests     # unit tests with coverage
make lint      # ruff
make build     # sdist + wheel into dist/
make html      # regenerate the example gallery

make lint runs ruff check. The formatter is intentionally not enforced; see the note in pyproject.toml for why.

Rendering is deterministic, which makes it easy to prove a change did not alter output: render the casts in docs/examples/casts/ before and after, and compare bytes.

Credits

termtosvg was created by Nicolas Bedos, who wrote the recorder, the rendering engine and the template system. This repository continues from that work.

Licensed under the BSD 3-Clause License.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

termtosvg_ng-1.2.0.tar.gz (75.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

termtosvg_ng-1.2.0-py3-none-any.whl (77.7 kB view details)

Uploaded Python 3

File details

Details for the file termtosvg_ng-1.2.0.tar.gz.

File metadata

  • Download URL: termtosvg_ng-1.2.0.tar.gz
  • Upload date:
  • Size: 75.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for termtosvg_ng-1.2.0.tar.gz
Algorithm Hash digest
SHA256 0844d606035e5fcdaaa174febf88e6bb30af2e0b7fc40666a8beccf3de4d8152
MD5 953b4453b71d13e1389f40ae1b5fc781
BLAKE2b-256 86fa0e41c0684487b6f01a0317e3307dc8c0ede6c8395eaa3edc085547c25e45

See more details on using hashes here.

Provenance

The following attestation bundles were made for termtosvg_ng-1.2.0.tar.gz:

Publisher: release.yml on gaborini/termtosvg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file termtosvg_ng-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: termtosvg_ng-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 77.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for termtosvg_ng-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 17db8e2d22834b5d19b8511ebe9417264b5185e10b3314ea302b147cc901f096
MD5 5ffde001678093cd7e97cfdb0256ccef
BLAKE2b-256 22f4f8a271321dfc3d071438f93152774bf10fc4dd688c0f02355ffcd6a8c427

See more details on using hashes here.

Provenance

The following attestation bundles were made for termtosvg_ng-1.2.0-py3-none-any.whl:

Publisher: release.yml on gaborini/termtosvg

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page