Skip to content

Commit bd68a04

Browse files
committed
demo: apt-free GIF recorder (static asciinema v3 + agg + bundled ttf)
The recorder no longer apt/pip-installs python (~100MB, slow). It uses single static binaries + one font file: - scripts/fetch-recording-tools.sh fetches asciinema (v3 Rust binary), agg, and JetBrainsMono-Regular.ttf into scripts/.recorder-bin/ (gitignored). Honors ALL_PROXY/HTTPS_PROXY for firewalled networks. - scripts/Dockerfile.recorder is now pure COPY — zero apt — so the recorder image builds in seconds. - record scripts use 'asciinema rec -f asciicast-v2' (v3 binary defaults to v3, which agg 1.5 can't read) and 'agg --font-dir ... --font-family JetBrains Mono' (agg is statically linked and needs only a .ttf, no fontconfig/apt). Verified end-to-end: recorder image builds with no apt, records, and renders a GIF with the bundled font.
1 parent 26bad3f commit bd68a04

5 files changed

Lines changed: 51 additions & 19 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ coverage.txt
3434
# Local-only working docs (not for public repo)
3535
/REVIEW_ISSUES.md
3636
/.claude/
37+
38+
# Recording tool binaries (fetched via scripts/fetch-recording-tools.sh)
39+
/scripts/.recorder-bin/

scripts/Dockerfile.recorder

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
# Recorder image: rewindable-claude + asciinema + agg, so make-claude-gif.sh
2-
# can record without re-installing the (slow) python/asciinema stack every run.
3-
# docker build --platform=linux/arm64 -f scripts/Dockerfile.recorder \
4-
# --build-arg AGG_LOCAL=... -t rewindable-claude-rec scripts/ (see make-claude-gif.sh)
1+
# Recorder image: rewindable-claude + asciinema + agg + a monospace font, so
2+
# make-claude-gif.sh / record-claude-tui.sh can record without any apt/pip
3+
# install. asciinema (v3) and agg are single static binaries; the only other
4+
# need is one .ttf for agg's renderer. Populate the build context first:
5+
# bash scripts/fetch-recording-tools.sh # → scripts/.recorder-bin/
6+
# docker build -f scripts/Dockerfile.recorder -t rewindable-claude-rec scripts/
57
FROM rewindable-claude
68

7-
RUN sed -ri 's#deb\.debian\.org#mirrors.aliyun.com#g' /etc/apt/sources.list.d/*.sources 2>/dev/null || true \
8-
&& apt-get update -qq \
9-
&& apt-get install -y -qq python3-pip fonts-dejavu-core >/dev/null 2>&1 \
10-
&& (pip3 install --quiet --break-system-packages --index-url https://mirrors.aliyun.com/pypi/simple/ asciinema \
11-
|| pip3 install --quiet --break-system-packages asciinema)
9+
# Static tools (no apt, no python). asciinema v3 records; agg renders cast→GIF.
10+
COPY .recorder-bin/asciinema /usr/local/bin/asciinema
11+
COPY .recorder-bin/agg /usr/local/bin/agg
12+
COPY .recorder-bin/JetBrainsMono-Regular.ttf /usr/local/share/fonts/JetBrainsMono-Regular.ttf
13+
RUN chmod 0755 /usr/local/bin/asciinema /usr/local/bin/agg
1214

13-
# agg (the cast→GIF renderer) is copied in from the build context.
14-
COPY agg /usr/local/bin/agg
15-
RUN chmod 0755 /usr/local/bin/agg
15+
# agg looks fonts up by directory; point demos at this one.
16+
ENV AGENTENV_GIF_FONT_DIR=/usr/local/share/fonts AGENTENV_GIF_FONT="JetBrains Mono"
1617

17-
# Restore the rewindable-claude entrypoint (FROM inherits it, but be explicit).
1818
ENTRYPOINT ["/usr/local/bin/rewindable-claude-entrypoint"]

scripts/fetch-recording-tools.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
# Fetch the static tools the GIF recorder needs — asciinema (v3, single Rust
3+
# binary), agg (cast→GIF renderer), and one monospace .ttf — into
4+
# scripts/.recorder-bin/. No apt, no pip, no python: scripts/Dockerfile.recorder
5+
# just COPYs these in.
6+
#
7+
# Behind a firewall? Route through a proxy, e.g.:
8+
# ALL_PROXY=socks5h://127.0.0.1:13659 bash scripts/fetch-recording-tools.sh
9+
# (curl honors ALL_PROXY/HTTPS_PROXY.) Override an arch with ARCH=x86_64.
10+
set -euo pipefail
11+
cd "$(dirname "$0")"
12+
mkdir -p .recorder-bin
13+
ARCH="${ARCH:-$(uname -m | sed 's/arm64/aarch64/;s/amd64/x86_64/')}"
14+
ASC_VER="${ASC_VER:-3.2.1}"
15+
AGG_VER="${AGG_VER:-1.5.0}" # 1.5 reads asciicast-v2 (we record with -f asciicast-v2)
16+
17+
get() { echo "fetching $2"; curl -fL -m 300 -o "$1" "$2"; }
18+
19+
get .recorder-bin/asciinema \
20+
"https://github.com/asciinema/asciinema/releases/download/v${ASC_VER}/asciinema-${ARCH}-unknown-linux-gnu"
21+
get .recorder-bin/agg \
22+
"https://github.com/asciinema/agg/releases/download/v${AGG_VER}/agg-${ARCH}-unknown-linux-gnu"
23+
get .recorder-bin/JetBrainsMono-Regular.ttf \
24+
"https://github.com/JetBrains/JetBrainsMono/raw/master/fonts/ttf/JetBrainsMono-Regular.ttf"
25+
26+
chmod +x .recorder-bin/asciinema .recorder-bin/agg
27+
echo "ok → scripts/.recorder-bin/ (build: docker build -f scripts/Dockerfile.recorder -t rewindable-claude-rec scripts/)"

scripts/make-claude-gif.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,15 @@ docker run --rm --platform="$PLATFORM" \
3737
--entrypoint bash \
3838
"$IMAGE" -c '
3939
set -e
40-
command -v asciinema >/dev/null || { echo "recorder image missing asciinema — build scripts/Dockerfile.recorder" >&2; exit 1; }
40+
command -v asciinema >/dev/null || { echo "recorder image missing asciinema — fetch-recording-tools.sh + build scripts/Dockerfile.recorder" >&2; exit 1; }
4141
4242
# /rec.sh (mounted) invokes the image entrypoint → supervise --self-rollback
43-
# -- claude. asciinema records the real Claude Code session.
44-
TERM=xterm-256color asciinema rec --overwrite --cols 100 --rows 30 \
43+
# -- claude. asciinema (v3 binary) records in v2 so agg 1.5 can read it.
44+
TERM=xterm-256color asciinema rec --overwrite -f asciicast-v2 --cols 100 --rows 30 \
4545
-c "bash /rec.sh" /out/claude-rewind.cast
4646
47-
agg --theme monokai --speed 1.5 --font-size 15 /out/claude-rewind.cast /out/claude-rewind.gif
47+
agg --font-dir "${AGENTENV_GIF_FONT_DIR:-/usr/local/share/fonts}" --font-family "${AGENTENV_GIF_FONT:-JetBrains Mono}" \
48+
--theme monokai --speed 1.5 --font-size 15 /out/claude-rewind.cast /out/claude-rewind.gif
4849
ls -la /out/claude-rewind.cast /out/claude-rewind.gif
4950
'
5051
echo "wrote: $(pwd)/docs/claude-rewind.gif"

scripts/record-claude-tui.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,11 @@ docker run --rm -it --platform="$PLATFORM" \
3737
echo " Exit with Ctrl-D when done — the GIF will render."
3838
echo
3939
sleep 2
40-
TERM=xterm-256color asciinema rec --overwrite --cols 100 --rows 30 \
40+
TERM=xterm-256color asciinema rec --overwrite -f asciicast-v2 --cols 100 --rows 30 \
4141
-c "/usr/local/bin/rewindable-claude-entrypoint claude --permission-mode acceptEdits" \
4242
/out/claude-rewind.cast
43-
agg --theme monokai --speed 1.2 --font-size 15 /out/claude-rewind.cast /out/claude-rewind.gif
43+
agg --font-dir "${AGENTENV_GIF_FONT_DIR:-/usr/local/share/fonts}" --font-family "${AGENTENV_GIF_FONT:-JetBrains Mono}" \
44+
--theme monokai --speed 1.2 --font-size 15 /out/claude-rewind.cast /out/claude-rewind.gif
4445
echo "wrote docs/claude-rewind.gif"
4546
'
4647
echo "wrote: $(pwd)/docs/claude-rewind.gif"

0 commit comments

Comments
 (0)