Claude Media
Claude CodeでTikZの図を描く — コンパイル結果のPNGを見て直させる

Claude CodeでTikZの図を描く — コンパイル結果のPNGを見て直させる

TikZの図を単体でコンパイルしてPNGにし、Claude Codeに画像として読ませて座標のずれを直させる手順です。standalone、pdftoppm、権限設定、CLAUDE.mdの書き方を扱います。

TikZで論文の図を描くと、座標の数字を直しては再コンパイルし、PDFを開いて見比べる作業が延々と続きます。この往復を、コンパイル → PNG化 → Claude Codeが画像を見て直す、というループに置き換えるのが本記事の手順です。

要点は3つです。図を1枚だけ standalone クラスでコンパイルする。pdftoppm でPNGにする。そのPNGをClaude Codeに読ませて、ずれた箇所のソースを直させる。論文本体の組版を毎回回さないので、ループが短く済みます。

なぜPNGを経由させるのか

LaTeXのコンパイルログが教えてくれるのは、文法の誤りや足りないパッケージまでです。矢印が重なっている、ラベルが枠からはみ出している、といった見た目の問題は、ログには何も出ません。

Claude Codeは画像を見られます。Readツールは、PNG・JPEG・GIF・WebPを生のバイト列ではなく、モデルが見られる視覚コンテンツとして返します。common-workflowsの「Work with images」節も、画像パスを渡して分析させる使い方を挙げています。

Analyze this image: /path/to/your/image.png

画像を扱えるなら、見た目の確認も任せられます。TikZのソースは座標の数字の集まりなので、「左のノードがどれだけ右にずれているか」を画像から読み取って数字に戻す作業は、Claude Codeの得意な範囲に入ります。

ただし、読ませる画像には癖があります。Claude Codeは大きな画像をモデルの上限に合わせて縮小・再圧縮してから送ります。細部が潰れて見えるときは、切り出した画像を読ませるよう公式のツール説明も勧めています。この点は後半の対処で使います。

前提: 必要な環境

この手順で使うのは、TeXの処理系、PDFをPNGにするコマンド、実行権限を付けたスクリプトの3つです。

  • TeX Live: lualatex(または pdflatex)と、standalone・tikz パッケージ。日本語ラベルを使うなら luatexja も要ります
  • poppler: pdftoppm コマンドを含みます
  • scripts/fig.sh の実行権限

popplerは、macOSならHomebrewで、Debian系Linuxなら poppler-utils パッケージで入ります。

# macOS
brew install poppler
 
# Debian / Ubuntu
sudo apt install poppler-utils
 
# スクリプトに実行権限を付ける(後述の fig.sh を作ったあとで)
chmod +x scripts/fig.sh

chmod +x を忘れると、あとで Bash(scripts/fig.sh *) を許可しても、スクリプトの実行そのものが失敗します。許可は「確認なしで通す」だけで、実行できるようにはしてくれません。

図を単体でコンパイルする準備

論文の main.tex を毎回コンパイルすると、参考文献や相互参照の解決まで走ります。図だけを直したいときは無駄です。そこで図を別ファイルに切り出し、standalone クラスで単体の文書にします。

standaloneは、TeXの図をそれだけでコンパイルすることも、本体文書の一部として取り込むこともできるクラスです。CTANの説明では、既定でpreviewパッケージを使い、余白なしで組版結果を表示するとあります。図の周りの余白が切り詰められるので、PNGにしたときに図だけが写ります。

% figures/pipeline.tex
\documentclass[tikz,border=4pt]{standalone}
\usepackage{luatexja}
\usetikzlibrary{positioning,arrows.meta}
 
\begin{document}
\begin{tikzpicture}[
  box/.style={draw, rounded corners, minimum width=2.4cm,
              minimum height=0.9cm, align=center},
  >={Stealth}
]
  \node[box] (in)  {入力};
  \node[box, right=1.2cm of in]  (enc) {エンコーダ};
  \node[box, right=1.2cm of enc] (out) {出力};
  \draw[->] (in) -- (enc);
  \draw[->] (enc) -- (out);
\end{tikzpicture}
\end{document}

論文側では \includegraphics{figures/pipeline.pdf} で取り込めます。上の例は、ノードを座標の数字ではなく相対位置で並べる書き方にしています。理由は後ほど説明します。

ラベルに日本語を使うので、luatexja を読み込み、次のスクリプトも lualatex で組版します。pdflatex は日本語をそのままでは組めないためです。ラベルを英字だけにするなら \usepackage{luatexja} の行は要らず、スクリプトの ENGINE を pdflatex に替えれば動きます。論文本体が別のエンジンやフォント設定を使っている場合は、図のファイルも本体と同じ設定に揃えてください。

ビルドとPNG化を1本のスクリプトにする

コンパイルとPNG化は、Claude Codeが毎回同じ形で呼べるよう、スクリプトにまとめます。

#!/bin/sh
# scripts/fig.sh  使い方: scripts/fig.sh figures/pipeline.tex
set -e
ENGINE="${ENGINE:-lualatex}"   # 英字だけの図なら pdflatex でも可
src="$1"
dir=$(dirname "$src")
name=$(basename "$src" .tex)
 
# 前回の成果物を消す。失敗時に古いPNGが残ると、直っていない図を読んでしまう
rm -f "$dir/$name.pdf" "$dir/$name.png"
 
"$ENGINE" -interaction=nonstopmode -halt-on-error \
  -output-directory "$dir" "$src" > "$dir/$name.log.txt" 2>&1 \
  || { echo "build failed: $dir/$name.log.txt"; tail -n 30 "$dir/$name.log.txt"; exit 1; }
 
pdftoppm -png -r 150 -singlefile "$dir/$name.pdf" "$dir/$name"
echo "wrote $dir/$name.png"

poppler 26.08.0の pdftoppm -h では、使うオプションは次のとおりです。

オプション意味
-png意味PNGで出力する
-r <数値>意味解像度(DPI)。既定は150
-singlefile意味先頭ページだけを書き出し、ファイル名に連番を付けない
-x -y -W -H意味切り出し領域の左上座標と幅・高さ

standalone の出力は1ページなので、-singlefile を付けると pipeline.png という名前で書き出されます。コンパイルに失敗したときはログの末尾30行だけを標準出力に流します。ログ全体を読ませるとコンテキストを食うためです。ログ本体は図と同じ figures/ に残るので、末尾で原因が切れていても後から読めます。

Claude Codeに渡す指示

スクリプトができたら、依頼は次のように書きます。直す対象と、直したかどうかの判定基準を一緒に渡すのがコツです。

figures/pipeline.tex を直してください。
scripts/fig.sh figures/pipeline.tex でPNGを作り、そのPNGを読んで確認します。
直す点: 出力ノードが図の右端で切れている。矢印とラベルが重なっている。
直したらもう一度ビルドしてPNGを読み、2点が解消したか報告してください。

Claude Codeは、ソースを編集 → スクリプト実行 → PNGをRead、という順で進みます。見た目が合うまでこのループを繰り返すので、人間が間に入るのは仕上がりの確認だけです。

毎回この文面を書かなくて済むよう、決まりごとはCLAUDE.mdに置きます。

## TikZの図
 
- 図は figures/*.tex に standalone クラスで1枚ずつ置く
- 確認は scripts/fig.sh figures/<名前>.tex を実行し、出力されたPNGを読む
- 座標は絶対値より相対位置(right=1.2cm of ...)を優先する
- ノード間隔など数値の変更は1回に1か所。変えたらPNGを読み直す

最後の行が効きます。複数の数値を一度に動かすと、どの変更がずれを直し、どれが新しいずれを作ったのか、画像だけでは判別しにくくなるためです。

座標のずれを直させるときのTikZ側の作り

画像から読み取れるのは「だいたいどのくらいずれているか」までで、ピクセル単位の正確さは期待できません。そのため、ソースの側を、多少ずれても崩れにくい書き方にしておくと直しやすくなります。

TikZのマニュアルは、座標の前に ++ を付けると相対座標になると説明しています。++(1cm,0pt) は、直前の位置から右に1cmの点を指し、そこが新しい現在位置になります。絶対座標で全ノードを並べると、1つ動かしたときに残りを全部直す羽目になります。相対指定や right=1.2cm of in のようなpositioningライブラリの書き方なら、1か所の変更が後ろのノードに自然に伝わります。

もう1つ、マニュアルに載っている注意点があります。自動アンカー座標(ノードの境界上の点)と相対座標を組み合わせると、相対座標は境界点ではなく、ノードの中心から計算されます。「枠の端から少し離したつもりが、中心基準でずれる」ときは、この仕様が原因かもしれません。Claude Codeに原因を探させるときは、この点を指示に含めると、無関係な座標の書き換えを避けられます。

権限を絞って自動で回す

ループを人の承認待ちで止めないよう、スクリプトの実行だけを許可します。permissionsのBashルールは、サブコマンドの後ろに * を置く形で書きます。

{
  "permissions": {
    "allow": [
      "Bash(scripts/fig.sh *)",
      "Read(./figures/**)",
      "Edit(./figures/**)"
    ]
  }
}

これを .claude/settings.json に置くと、scripts/fig.sh の呼び出しと figures/ 配下の読み書きが、確認なしで通ります。TeXエンジン(lualatex など)を直接許可するより、決まった引数で実行されるスクリプトだけを許可するほうが、実行内容を絞れます。

ループで起きやすいつまずき

落とし穴

コンパイルが失敗したのに古いPNGが残る

-halt-on-error は最初のエラーで処理を止めるため、PDFが作られません。前回のPNGが残っていると、直っていない図を「直った」と読み違えます。スクリプトの先頭で古いPDFとPNGを消しているのはこのためです。失敗時はPNGが存在しないので、Claude Codeは失敗に気づいてログを見に行けます。

つまずき

TikZのループで止まる4つの原因

  • PNGが縮小されて細部が読まれない

    大きな図ほど、Claude Codeに渡る時点で縮小されます。小さな添字や細い線のずれを指摘してもらえないときは、解像度を上げるのではなく、問題の領域だけを切り出して読ませます。pdftoppm の -x -y -W -H で切り出した別PNGを用意しておくと、確認の的が絞れます。

  • 切り出したPNGの置き場所で確認待ちになる

    上の permissions が読み取りを許可しているのは figures/ 配下だけです。切り出しを /tmp など別のディレクトリに書き出すと、Claude Codeがそれを読む段階で確認が出て、自動のループが止まります。切り出しも figures/crops/ のように許可範囲の中に出力してください。

  • ログの末尾30行では原因が切れている

    TeXのエラー行は ! で始まり、その前後に原因の手がかりが出ます。ログが長いと、末尾30行には後続の連鎖エラーしか写らないことがあります。その場合は grep -n -A5 '^!' figures/pipeline.log.txt で最初のエラー箇所だけを取り出させると、コンテキストを節約できます。ログは figures/ 内にあるので、追加の許可は要りません。

  • 日本語ラベルで文字化け・コンパイル失敗になる

    pdflatex に日本語を渡すと、文字が出力されないか、エンコーディング関係のエラーで止まります。上の例のように lualatex と luatexja を使うか、ラベルを英字にして ENGINE=pdflatex で回してください。論文本体が別の日本語エンジンを使っているなら、図のファイルもそれに合わせます。

画像で直せる範囲と、人が見るべき範囲

このループが得意なのは、ノードのはみ出し、矢印とラベルの重なり、間隔の不揃いのような、画面を見て分かる崩れです。一方で、次の点は画像を読ませても保証されません。

  • 論文の投稿規定にある、図の線幅・フォントサイズ・色の条件に合っているか
  • 白黒印刷したときに色分けが判別できるか
  • 図が示す内容そのものが、本文の主張と合っているか

最後の点は特に、Claude Codeが「見た目として整った」と報告しても、内容の正しさとは別の話です。仕上げの確認は、PDFとして人間の目で行ってください。

ループに入る前に、lualatex が使える環境で上の pipeline.tex を scripts/fig.sh figures/pipeline.tex で1度ビルドし、PNGが期待どおりの形になるかを確かめておくと安全です。

まとめ

TikZの図直しは、standaloneで単体コンパイルし、PNGにして読ませる形にすると、ログに出ない見た目の崩れをClaude Codeが拾えます。効きどころは、ビルドを1本のスクリプトに固めること、数値の変更を1回1か所に限ること、座標を相対指定で書くことの3つです。画像が縮小される点を踏まえ、細部は切り出して読ませます。

PDFの生成元を直す別の例はveraPDFの違反をTypst・HTML・LaTeXの生成元から直す手順に、LaTeXで文書を組む流れはMarkdownから縦書き日本語PDFを作る手順にあります。コマンド実行の結果を渡して直させる型は、criterionの結果を読んで遅い関数を直す手順も同じ構造です。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. code.claude.com/docs/en/common-workflows
  2. code.claude.com/docs/en/tools-reference
  3. tikz.dev/
この記事を共有:XはてブLinkedIn