animate-file-history
リポジトリのライフ全体で、特定のファイルがどのように見えたかをGIF(またはMP4)に変換します。リクエストは自然言語($ARGUMENTS)で行われます。あなたの仕事は、対象ファイルを特定し、Gitからそれらの全バージョンを収集し、各バージョンをレンダリングし、前のバージョンと視覚的に同じものを除外し、残ったものをアニメーションに連結することです。
バンドルされたスクリプトがGitの走査、レンダリング、視覚的重複除去、エンコードを実行します:
scripts/animate-history.sh。このスキルのベースディレクトリを基準としており、ユーザーのリポジトリを基準にはしません。以下、$SKILL はそのディレクトリを表します。スクリプトは絶対パスで呼び出してください。--help ですべてのオプションを表示できます。あなたの役割はファイルを選択し、ページの場合はスクリーンショットを生成することです。
1. ツールの確認
command -v git ffmpeg rsvg-convert; ls "/Applications/Google Chrome.app" 2>/dev/null; command -v chromium google-chrome
ffmpeg は必須です。SVGには rsvg-convert(brew install librsvg / apt install librsvg2-bin)またはChrome/Chromiumが必要です。--label のキャプションとHTMLページにはChrome/Chromiumが必要です(CHROME=/path で検出を上書きできます)。不足しているものがあれば、何が不足しているかとそのインストール方法を伝えてください。SVGバージョンを黙ってスキップしないでください。
2. リクエストをファイルに解決する
現在のツリーだけでなく、現在のブランチの全履歴を検索してください。ロゴはリネーム、移動、再エクスポートされることがあり、削除されたファイルもストーリーに含まれます:
git log --format= --name-only -- ':(glob,icase)**/*logo*' | sort -u
ユーザーの単語だけでなく、そのものが何と呼ばれているかで検索してください。ロゴは favicon*、apple-touch-icon*、*mark*、*lockup*、*wordmark*、*brand*、そして製品名自体にも含まれます。初期バージョンはしばしばファビコンだけに存在します。それに応じてGlobリストを拡張し、返ってきた結果を確認してください。
レンダリング可能なタイプに絞り込む:画像は png jpg jpeg gif webp bmp svg、静的ページは html。ビルド出力やベンダーコピー(dist/、build/、node_modules/、.next/)は無視してください。
次に、一致したものを**系統(lineage)**にグループ化します。1系統につき1つのアニメーションです:
- リネーム、移動、またはフォーマット変更をまたいだ同じアートワーク(
logo.png→brand/logo.svg)は1つの系統です。すべてのパスを1回の実行で渡します。スクリプトが日付順にマージして単一のタイムラインにします。 - 共存するバリアント(
logo-dark.svg、logo-mono.svg、favicon.png、サイズ別エクスポートの[email protected]など)は別々の系統です。デフォルトでは1系統につき1アニメーションとし、リクエストが合理的に意味するバリアントのみをアニメーション化します(通常はプライマリロゴであり、すべてのファビコンサイズではありません)。
グループ化が本当に曖昧な場合(複数の無関係な「ロゴ」ファイルがある、または一致するものがない)、コミット数(git log --follow --oneline -- <path> | wc -l)を付けて候補リストを表示し、レンダリング前に質問してください。
3a. 画像:スクリプトを実行
"$SKILL/scripts/animate-history.sh" -o logo-history.gif --label <path> [<older-path> ...]
便利なオプション:-s 512 または -s 1200x800 のキャンバスサイズ、-t 0.25 バージョンごとの表示時間(画像のデフォルト;ページスクリーンショットの --frames ではデフォルト0.8秒;ユーザーが指定した値があればそれを使用、例:「0.5秒/フレーム」→ -t 0.5)、--hold 1.5 最終フレームの保持時間、--bg '#0b0b0b' 暗い背景用ロゴ、--keep DIR フレームを保持、-o x.mp4 動画出力、--skip <sha>(繰り返し可)ユーザーが不要とするバージョンをスキップ。標準エラー出力に keep/skip(コミットごと)と kept N of M versions を表示します。
パスはカレントディレクトリ(または -C DIR)を基準として、任意のGitパススペックと同様です。リポジトリルートから実行し、履歴リストが示す通りにパスを渡してください。スクリプト自体がリネームを追跡するため(git log --follow)、通常は現在のパスだけで十分ですが、ファイルが新しい名前で再作成された場合は古いパスも必要です。.git 以外の場所からスクリプトを実行する場合は -C /repo を使用してください。
3b. ページ:各バージョンのスクリーンショットを取得し、フォルダに対してスクリプトを実行
ページは各コミットでレンダリングが必要です。ページのソース(index.html、app/page.tsx、src/pages/index.vue...)を見つけ、それ またはそのレンダリングに影響するもの に触れたコミットを一覧表示します。ホームページの見た目は、そのコンポーネントやCSSによっても変わります:
git log --format='%H %cs' --reverse -- <page file> <its components/styles dirs>
それが約40コミットを超える場合は、サンプリング(1週間または1ヶ月ごと、最初と最後を含む)し、その旨を伝えてください。スクリーンショットは <YYYY-MM-DD>_<short-sha>.png という名前の1つのフォルダに保存します。これでファイルが日付順に並び、名前がキャプションになります。
-
静的HTML:ビルドは不要。
git archive <sha> | tar -x -C "$snap"でコミットをエクスポートし、"$CHROME" --headless=new --hide-scrollbars --window-size=1280,800 --screenshot=... "file://$snap/<page>.html"でスクリーンショットを取得します。その後$snapを削除し、リポジトリの外に配置してください。 -
フレームワークページ(React、Next、Vue、Astro...):実行してレンダリングする必要があります。コミットごとに
snapshot-commit.shを使用します:"$SKILL/scripts/snapshot-commit.sh" -C <repo> -r /<route> -f https://<production site> <sha> "$shots"これはコミットをエクスポートし、そのコミット自身のロックファイル(ロックファイルごとにキャッシュ)をインストールし、開発サーバーを起動し(
npm run dev -- --port {port}以外の場合は-d 'cmd with {port}')、Playwright(scripts/screenshot-page.mjs、playwright-coreとChromeが必要 - リポジトリ自身のものはPLAYWRIGHT_DIRで見つける)でスクリーンショットを取得します。ネットワークアイドルとすべての<img>を待ち、Cookieバナーを閉じ、次のいずれかを1行出力します:ok、blank、error(「このブラウザでは読み込めません」などのエラーページ)、またはfail(インストールまたは開発サーバー)。okのみがPNGを書き込みます。これが数回以上のインストールを意味する場合は、実行前に質問してください。
アニメーション化する前に結果を確認し、ok だけを信頼しないでください:
- 現在の
node_modulesを決して流用しないでください。 古いコミットは、現在のツリーが削除したパッケージ(例:react-router-dom)をインポートしており、ページが空白でレンダリングされる可能性があります。そのため、スクリプトはコミットごとにインストールを行います。 blank/error/failコミット:開発ログを確認し、原因を一度修正してみてください(環境変数の欠落、誤った-dコマンド、--ignore-scriptsが必要なビルドステップをスキップしているなど)。それでも解決しない場合は、そのコミットをスキップし、スキップした数を報告してください。- 壊れた画像(
ok行にbroken-images=NとURLがある場合):開発サーバーが提供できないアセット(プラットフォームホストパス/__l5e/...、gitignoredファイル、アップロードファイルなど)。-f <production site>で本番環境からフェッチします。それでも画像が壊れている場合は、レポートでその旨を伝えてください。空のボックスだらけのGIFを黙って出力しないでください。後から報告するよりも、その場で修正してください。 - 最終実行前に、フレームのコンタクトシートを確認してください(
ffmpeg -pattern_type glob -i '*.png' -vf scale=320:-1,tile=6x6 -frames:v 1 sheet.png)。
その後:
"$SKILL/scripts/animate-history.sh" --frames "$shots" -s 1280x800 --label -o home-page-history.gif
同一のスクリーンショットは画像と同様に除外され、空白のもの(単一色)も除外されます(--keep-blank で保持可能)。すべてのショットに固定ウィンドウサイズを使用し、長いページや詳細なページでは -o x.mp4 を優先してください。フルページのGIFは大きくなります。
3c. 複数のリポジトリにまたがる場合
ロゴが複数のリポジトリ(アプリ、ダッシュボード、ウェブサイト)に存在する場合、各リポジトリで --keep <dir> と --label なしでスクリプトを実行し、その後、保持された各フレームを <YYYY-MM-DD>_<repo>-<short-sha>.png という名前の1つのフォルダにコピーします。標準エラー出力の keep 行は、各保持フレームの日付とSHAを順に表示します。名前が衝突する場合(1つのコミットで複数のファイルが変更された場合)は -2、-3 などを追加します。その後、マージされたフォルダに対して --frames <folder> --label -t 0.25 を実行し、すべてのリポジトリにわたる単一のタイムラインを作成します。
4. レポート
出力パス、見つかったバージョン数とアニメーションに含まれた数、日付範囲、およびスキップされたもの(レンダリング不可、ビルド失敗、サンプリング対象外)を報告してください。求められたら開いてください(open x.gif)。出力はユーザーが希望する場所に書き込み、デフォルトはカレントディレクトリとします。求められない限りコミットしないでください。
注意点
- 重複除去はレンダリングされたピクセルに基づき、バイト単位ではありません。 再エクスポートされたPNGや再フォーマットされたSVGは、同一のレンダリング結果であればスキップされます。1ピクセルのずれがあれば変更としてカウントされます。それがポイントです。バイトレベルフィルターを追加しないでください。
- 外部ファイルを参照するSVG(フォント、
<image href>)は、履歴から取得されるのはSVG自体のみであるため、それらなしでレンダリングされます。埋め込みコンテンツは問題ありません。 - アニメーションGIFソースは最初のフレームのみが使用されます。
- マージコミットは走査されません。
git logは、そのファイルの変更を、変更を行ったブランチ上で表示します。これはタイムラインとして望ましい動作です。 - シャロークローン(CI、
--depth 1)には履歴がありません。git rev-parse --is-shallow-repositoryで確認し、trueが出力された場合はgit fetch --unshallowを提案してください。 - キャプションにはChrome/Chromiumが必要です。バンドルされているffmpegビルドには
drawtextが欠けていることが多いためです。
モデルと努力量
ここでの判断は小規模です(ファイルの選択、系統のグループ化、サンプルの選択)。重い処理はスクリプトとシェルループが行います。デフォルトは Sonnet、低努力 に設定してください。Opusやそれ以上の努力量はこのタスクに何ももたらさず、フォークやサブエージェントも不要です。努力量を上げるのは、系統のグループ化が本当に曖昧な場合のみです。
ほとんどの実行のトークンは、セッションの継承コンテキスト(CLAUDE.md、スキルとツールのリスト、約100k以上)であり、毎ターンキャッシュから再読み込みされます。作業自体ではありません。負荷の少ないセッションでの実行は、負荷の多いセッションでの実行よりもはるかにコストが低くなります。
ベンチマーク
セッションのトランスクリプトを使用して測定します(アシスタントの応答ごとの usage を合計):
f=$(ls -t ~/.claude/projects/<project-dir>/*.jsonl | head -1)
jq -s '[.[]|select(.message.usage)|.message.usage]|{turns:length,out:(map(.output_tokens)|add),cache_read:(map(.cache_read_input_tokens)|add),cache_create:(map(.cache_creation_input_tokens)|add)}' "$f"
| 日付 | モデル / 努力量 | タスク | ターン数 | 出力トークン | キャッシュ読み取り | キャッシュ作成 | 結果 |
|---|---|---|---|---|---|---|---|
| 2026-10-23 | Sonnet 5.5 / low | storraホームページ、発見のみ(レンダリング前) | 9 | 3.6k | 731k | 134k | ファイル+ルート履歴が約7回の呼び出しで発見 |
実行ごとに行を追加してください(発見だけでなく完全実行)。Sonnet-low実行が系統またはサンプリングを誤った場合にのみ、Opus / より高い努力量と比較してください。