Skip to content

Recording & Export ​

Tachikoma has a built-in recording system that captures terminal output and exports to animated GIF and SVG. Recordings work both interactively (via hotkey) and programmatically (for documentation and CI).

Interactive Recording ​

Ctrl+R Workflow ​

Press Ctrl+R during any running app to start a recording:

  1. A 5-second countdown appears: "Recording in 5..."

  2. After the countdown, frame capture begins silently

  3. Use the app normally — every rendered frame is captured

  4. Press Ctrl+R again to stop

  5. A .tach file is saved: tachikoma_2026-02-18_143022.tach

  6. An export modal appears

Export Modal ​

The modal lets you choose output formats and configure rendering:

export_modal example
KeyAction
↑/↓Navigate options
SpaceToggle format selection or embed option
◀/▶Cycle font or theme
EnterExport selected formats (runs in background)
EscDismiss modal

Export preferences (font, formats, theme, embed) are saved to LocalPreferences.toml and persist across sessions.

Output Formats ​

.tach (Native Binary) ​

The native recording format. Compact, lossless, and supports all Tachikoma features including pixel data. Files are Zstd-compressed.

julia
# Load a .tach file
width, height, cells, timestamps, pixels = load_tach("recording.tach")

# Re-export to other formats
export_gif_from_snapshots("recording.gif", width, height, cells, timestamps;
                          pixel_snapshots=pixels)
export_svg("recording.svg", width, height, cells, timestamps)

.gif (Animated GIF) ​

Animated GIF with per-frame timing, 256-color quantization, and LZW compression. Requires a TrueType/OpenType font for glyph rendering.

Note

GIF export requires the FreeTypeAbstraction and ColorTypes packages. Call enable_gif() or add them to your project to activate the extension.

.svg (Animated SVG) ​

SMIL-based animation with discrete frame visibility. Supports font embedding via base64 @font-face, braille character rendering as dot patterns, and Unicode block elements as rectangles.

SVG export works without any extra dependencies.

Programmatic Recording ​

record_app ​

Record a Model headlessly — no terminal needed:

julia
record_app(model::Model, filename::String;
           width=80, height=24, frames=120, fps=30,
           events=Event[])

The model runs through its normal lifecycle (view is called frames times) and output is captured to a .tach file. Inject events at specific frames to simulate interaction:

julia
events = [
    (30, KeyEvent(:down)),    # frame 30: press down
    (60, KeyEvent(:enter)),   # frame 60: press enter
    (90, KeyEvent(:escape)),  # frame 90: press escape
]
record_app(MyModel(), "demo"; width=80, height=24, frames=120, events=events)

record_widget ​

Record a single widget's rendering:

julia
record_widget(filename, width, height, num_frames; fps=10) do buf, area, frame
    # Render your widget for this frame
    progress = frame / num_frames
    render(Gauge(progress; label="$(round(Int, progress*100))%"), area, buf)
end

The callback receives (buf, area, frame_idx) and is called once per frame. A 4-argument form (buf, area, frame_idx, frame) is available for pixel-producing widgets.

record_gif ​

Record directly to GIF without an intermediate .tach file:

julia
record_gif("demo.gif", 80, 24, 100; fps=15,
           font_path="/path/to/JetBrainsMono.ttf",
           font_size=14, cell_w=10, cell_h=20)

The callback form is the same as record_widget.

Font Discovery ​

Tachikoma scans standard system directories for monospace fonts:

julia
fonts = discover_mono_fonts()
# → [(name="JetBrains Mono", path="/Library/Fonts/JetBrainsMono.ttf"), ...]

The export modal uses this list for the font picker. Scanned directories:

  • macOS: /System/Library/Fonts, /Library/Fonts, ~/Library/Fonts

  • Linux: /usr/share/fonts, /usr/local/share/fonts, ~/.local/share/fonts

  • Windows: C:\Windows\Fonts

GIF Extension Setup ​

GIF export is a weak dependency. Enable it with:

julia
enable_gif()

This calls Base.require for FreeTypeAbstraction and ColorTypes. If those packages aren't installed, you'll get an error with installation instructions.

Check if the extension is loaded:

julia
gif_extension_loaded()  # → Bool

Export from .tach Files ​

Load a previously saved recording and re-export with different settings:

julia
w, h, cells, ts, pixels = load_tach("recording.tach")

# GIF with a specific font
export_gif_from_snapshots("recording.gif", w, h, cells, ts;
    pixel_snapshots=pixels,
    font_path="/path/to/font.ttf",
    font_size=16, cell_w=10, cell_h=20)

# SVG with embedded font
export_svg("recording.svg", w, h, cells, ts;
    font_path="/path/to/font.ttf")

The tachi Command-Line Tool ​

tachi renders .tach files without starting a REPL. It lives in tools/tachi in the repository and installs as a Julia app, which requires Julia 1.12 or later:

pkg> app add https://github.com/kahliburke/Tachikoma.jl:tools/tachi

Or equivalently:

julia
using Pkg
Pkg.Apps.add(url="https://github.com/kahliburke/Tachikoma.jl", subdir="tools/tachi")

This puts a tachi shim in ~/.julia/bin, which needs to be on your PATH. Update it later with pkg> app up Tachi and remove it with pkg> app rm Tachi.

tachi render demo.tach -o demo.gif --font "Meslo" --bg black
tachi demo.tach --start 20 --end 60 --scale 0.7
tachi info demo.tach     # frame count, dimensions, duration
tachi fonts              # list monospace fonts tachi can find

tachi render writes GIF by default; pass --format mp4 for MP4 via FFMPEG.jl. Run tachi --help for the full option list.

Preferences ​

Export settings persist in LocalPreferences.toml:

PreferenceDefaultDescription
export_font""Path to font file for GIF/APNG
export_formats"gif,svg"Comma-separated list of export formats
export_theme""Theme name for SVG colors
export_embed_fonttrueEmbed font in SVG via base64

These are set automatically through the export modal. To set them programmatically:

julia
save_export_prefs!("/path/to/font.ttf", Set(["gif", "svg"]);
                   theme_name="dracula", embed_font=true)