chang-07/cc-latex/tree/main/latex-render
latex-render
표시 수식 블록($$...$$ 또는 \[...\])을 tectonic으로 컴파일하고 pdftocairo로 래스터화한 뒤 kitty 그래픽 프로토콜을 통해 이미지로 그리는 Claude Code mod(function-hooks 플러그인)입니다.
이 mod 소개
latex-render는 cc-latex 프로젝트의 Claude Code 플러그인으로, 어시스턴트 응답의 표시 수식 블록($$...$$ 또는 [...])을 tectonic으로 컴파일하고 pdftocairo로 이미지로 변환한 뒤 kitty 그래픽 프로토콜로 대화 기록에 그립니다. 인라인 $x^2$는 텍스트로 유지됩니다. claude --plugin-dir ~/code/cc-latex/latex-render로 사용하며 kitty 그래픽을 지원하는 터미널(Ghostty 또는 kitty)과 PATH에 있는 tectonic 및 poppler가 필요합니다. tmux에서는 포함된 cc-tmux-bridge.py 브리지를 통해 passthrough 패킷을 중계할 수 있고 선택적 상수(PT_PER_ROW, CELL_ASPECT, TEXT_COLOR, DPI)로 모양을 조정할 수 있습니다.
설치
먼저 작성자의 README에서 marketplace와 플러그인 이름을 확인하세요. 저장소 구조에 따라 명령어가 달라질 수 있습니다.
claude plugin marketplace add chang-07/cc-latex claude plugin install latex-render
원문 / README
cc-latex
Typeset LaTeX inline in Claude Code replies.
A Claude Code mod (function-hooks plugin) that redraws assistant messages so
every display-math block ($$...$$ or \[...\]) is compiled with tectonic,
rasterised with pdftocairo, and drawn in the transcript as an image over the
kitty graphics protocol. Inline $x^2$ stays as text.
Requirements
- Claude Code 2.1.287+ with mods (function hooks) available
- A terminal that supports kitty graphics: Ghostty or kitty. (WezTerm and iTerm2 may work; untested.)
tectonicand poppler (pdftocairo) onPATH:brew install tectonic poppler
Install
git clone https://github.com/chang-07/cc-latex
claude --plugin-dir ~/code/cc-latex/latex-render
Ask Claude something with display math and the formulas appear typeset.
If you only see the LaTeX source, dimmed, where a formula should be, Claude Code's terminal probe decided images aren't supported. Skip the probe with:
CLAUDE_CODE_FORCE_TERMINAL_IMAGES=1 claude --plugin-dir ~/code/cc-latex/latex-render
Using tmux?
tmux drops the kitty graphics protocol, so by itself the mod shows formulas as
latex code blocks when it detects tmux. scripts/cc-tmux-bridge.py fixes
that. It runs Claude Code in a pty and wraps each graphics command in tmux's
passthrough envelope so it reaches the real terminal. Claude Code already uses
kitty's Unicode-placeholder mode under tmux, so no other change is needed.
tmux set -g allow-passthrough all # also put this in ~/.tmux.conf
python3 ~/code/cc-latex/scripts/cc-tmux-bridge.py claude --plugin-dir ~/code/cc-latex/latex-render
The bridge also answers Claude Code's image probe (no env flag needed),
measures the terminal's cell size so formulas are sized exactly, redraws tmux
once output goes quiet after an image, and keeps the terminal's image store
healthy: Claude Code deletes and re-uploads every image on each redraw, which
the bridge collapses to one upload per formula, and it evicts the oldest
images past CC_TMUX_BRIDGE_MAX_IMAGES (default 24) so the terminal never
hits its storage limit and starts refusing uploads silently. If formulas ever
stop appearing, a stuck store is the first suspect: send Ghostty
printf '\033Ptmux;\033\033_Ga=d,d=A\033\033\\\033\\' > $(tmux display -p '#{pane_tty}')
to clear it.
To make it automatic, put a claude wrapper earlier in PATH than the real
launcher that runs the bridge when $TMUX is set:
mkdir -p ~/.local/bridge-bin && cat > ~/.local/bridge-bin/claude <<'EOF'
#!/bin/sh
REAL="$HOME/.local/bin/claude"
BRIDGE="$HOME/code/cc-latex/scripts/cc-tmux-bridge.py"
if [ -n "$TMUX" ] && [ -z "$CC_TMUX_BRIDGE" ] && [ -t 1 ] && [ -f "$BRIDGE" ]; then
exec python3 "$BRIDGE" "$REAL" "$@"
fi
exec "$REAL" "$@"
EOF
chmod +x ~/.local/bridge-bin/claude
echo 'export PATH="$HOME/.local/bridge-bin:$PATH"' >> ~/.zshrc
scripts/tmux-placeholder-test.py draws a PNG in the current tmux pane with
placeholders, handy to check that your terminal + tmux combination can show
images at all.
How it works
hooks/register.tsx hooks ui.render for the AssistantMessage site. It
splits the message text around display-math blocks (skipping code fences),
returns the surrounding markdown as Markdown elements and each formula as an
Image. Rendering runs in the background: a formula not yet typeset shows as
dim $$ ... $$ text, and when its PNG is ready the hook calls
$.ui.invalidate('ui.render') so the message redraws with the picture.
Rendered PNGs are cached in ~/.cache/claude-latex/ by a hash of the LaTeX
source, white on transparent (dark terminals).
Tuning
Constants at the top of hooks/register.tsx:
| Constant | Default | Meaning |
| --- | --- | --- |
| PT_PER_ROW | 8 | Points of typeset height per terminal row. Lower = bigger. |
| CELL_ASPECT | 2.1 | Cell height / width of your terminal font, used when the bridge hasn't measured it. |
| TEXT_COLOR | white | Formula colour; use black on a light theme. |
| DPI | 600 | Rasterisation resolution; keep high, the picture is scaled to its cell box. |
Development
claude plugin validate latex-render
claude plugin test latex-render
