MotionLint について
MotionLintは、実行中のWebページのアニメーションを監査し、ビジョンLLMで複数ビューポートのデザインやユーザーフローもレビューできます。フロントエンド開発者やコーディングエージェント向けに、APIキー不要の決定論的検査とCI用レポートを提供します。
主な機能
- 01アニメーション時間とイージングの測定
- 02視覚効果を減らす設定の確認
- 03複数ビューポートでのデザインレビュー
- 04ユーザーフローのアニメーション撮影
- 05SARIF・HTMLレポートの生成
- 06stdio MCPサーバーの提供
活用シーン
- 01マージ前に不適切な動きを検出
- 02複数ビューポートでページ体験をレビュー
- 03登録フローのアニメーションを分析
- 04CIで重大なUX問題をゲート
MCP 対応
MotionLintはClaude CodeとCursor向けにstdio MCPサーバーを提供します。実行中ページのレビュー結果をコーディングワークフローに渡します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y motionlintANTHROPIC_API_KEYシークレットAnthropic API key for vision-LLM review. Optional — the deterministic audit needs no key, and Ollama, OpenAI or Google can be used instead.OPENAI_API_KEYシークレットOpenAI API key for vision-LLM review. Optional.GOOGLE_API_KEYシークレットGoogle API key for vision-LLM review. Optional.OPENAI_BASE_URLOverride the OpenAI base URL to target an OpenAI-compatible endpoint. Optional.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
5掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| url | string | はい | レビューする URL。 |
| model | string | いいえ | モデルの上書き設定。 |
| format | enum | いいえ | 出力形式(デフォルト:md)。'html' は見栄えがよく、共有しやすいレポートです。md | json | sarif | html |
| record | boolean | いいえ | キャプチャの動画を録画します。 |
| new_only | boolean | いいえ | 同じ URL の過去の実行で見つかっていない問題のみを報告します。 |
| provider | string | いいえ | LLM プロバイダーの上書き設定(auto|ollama|anthropic|openai|google|mock)。 |
| wait_for | string | いいえ | キャプチャ前に待機する CSS セレクターまたは 'networkidle'。 |
| viewports | array | いいえ | キャプチャするビューポート(デフォルト:mobile + desktop)。 |
| max_findings | number | いいえ | 重要度順に上位 N 件の指摘のみを残します(エージェントの注目点)。 |
| max_pr_annotations | number | いいえ | SARIF のみ:レポートごとに最大 N 件の結果を出力し、重大度順に並べます(レビュアーの疲労を防止)。 |
詳細
MotionLint
どんなページでも、アニメーションの品質を1つのコマンドでスコア化できます。APIキーも設定も不要です。
npx motionlint audit http://localhost:3000 --open
決定論的です。稼働中のページを測定し、LLMは使用しません。最初に一度だけ、npx playwright install chromiumを実行してください。
MotionLintは、アプリが実際に提供しているモーション(継続時間、イージング曲線、スタガー間隔、終了タイミング、動きを減らす設定への対応)を測定し、公開済みのアニメーション基準に照らしてスコア化します。ドロップダウンのイーズイン、600msのモーダル、0から拡大するカード、タッチ操作で発生するホバーモーションなどをすべて検出し、測定値と具体的な修正方法を提示します。
監査は無料で、オフラインで実行できます。APIキーを追加すると、MotionLintはビジョンLLMによるデザインレビューも行います。複数のビューポートのスクリーンショットと、実際のユーザージャーニーを50ms間隔で撮影したフレームバーストをモデルが評価し、ランク付けした指摘をコーディングエージェントに返します。Claude CodeやCursor内でMCP サーバーとして実行できます。
これが必要な理由
AIコーディングエージェントはJSX、HTML、CSSを読みますが、ユーザーが実際に見て、クリックし、アニメーションを目にするものは確認できません。プロンプトのルールはエージェントに「こうあるべき」という内容を伝えますが、実際に「どうなったか」を確認するものはありません。スライドインするはずのモーダルが突然表示されたり、ローディング状態が省略されたり、フォーカスリングが消えたりします。これらは差分には現れないため、マージ前のコードレビューでは検出できません。
MotionLintは、実行中のアプリを測定し、その評価をフィードバックすることで、このループを閉じます。
他との違い
| MotionLint | ビジュアルリグレッションツール(Percy、Chromatic、Playwright snapshots) | AIデザイン生成ツール(v0、Galileo、Claude Design、Stitch) | |
|---|---|---|---|
| 決定論的なモーション監査 | 13項目を稼働中のページから測定 — APIキー不要、$0 | ✗ | ✗ |
| 複数ビューポートのUXレビュー | 12の観点にわたる、ランク付けされた指摘 | ピクセル差分のみ | プロンプトから新しいレイアウトを生成 |
| アニメーションレビュー | CDPスクリンキャストで50ms間隔のフレームバーストを撮影 → コンタクトシートを作成 → LLMで評価 | ✗ | ✗ |
| 実行中アニメーションの調整 | Shadow DOMのプレビュー+スライダー+Claude Codeへのエクスポート | ✗ | 新しいモーションを生成しますが、既存のものは調整しません |
| ネイティブMCP サーバー | ✓ Claude Code / Cursor向けstdio MCP | ✗ | ツールによる |
| CIゲート | ✓ SARIF+コードスキャン用の終了コード | ✓ 画像差分のしきい値 | ✗ |
| 品質の検証 | 5つの最先端モデルで、24種類のフィクスチャを使ったストレステストの再現率100% | 該当なし | 該当なし |
MotionLintが解決する概念的なギャップは、ビジュアルリグレッションツールが「何が変わったか」は検出しても、新しいピクセルが「良いかどうか」は判断できず、AIデザインツールはゼロから生成しても、すでに実行中のものをレビューしないことです。MotionLintはビジョンLLMで実際の動作をレビューし、その評価をコーディングのループにフィードバックします。
まずはこちら — APIキーは不要です
npx playwright install chromium # one-time per machine (~300MB)
npx motionlint audit http://localhost:3000 --open
監査のセットアップはこれだけです。決定論的で、オフラインで実行でき、費用はかからず、読み込み可能なあらゆるURL(開発サーバー、ステージング環境、他の人のサイト)で動作します。Node 18以降が必要です。
チェック対象のルールはdocs/STANDARDS.mdで公開されています。インストールする前にお読みください。
次に:LLMデザインレビュー
1つのAPIキー(ANTHROPIC_API_KEY、OPENAI_API_KEY、GOOGLE_API_KEYのいずれか。無料で使うならOllamaをローカルで実行)を設定すると、さらに3つのコマンドで機能を利用できます。
npm install -g motionlint
# Multi-viewport UX review of a page → ranked findings across 12 dimensions.
motionlint review http://localhost:3000
# Animation review of a scripted user journey → frame contact sheet + report.
motionlint flow --spec flows/signup.json
# Interactive HTML tuner — every animation on the page, with live sliders.
motionlint tune http://localhost:3000
Claude Code / Cursor 内
claude mcp add motionlint -- npx -y motionlint mcp
すべてのフラグの概要 — CI ゲート、ルート検出、Storybook、ダークモード、ベースライン
# CI mode — non-zero exit on critical issues, SARIF output for code scanning.
motionlint review https://staging.acme.dev --ci --threshold critical --format sarif -o ux.sarif
# Polished, shareable HTML review with embedded screenshots + before/after fixes.
motionlint review http://localhost:3000 --format html -o review.html
# Review every route the site knows about (sitemap.xml + Next.js app/ directory).
motionlint review http://localhost:3000 --discover-routes
# Storybook mode — discover stories from /index.json, review each story iframe as its own route.
motionlint review http://localhost:6006 --storybook
# Color-scheme sweep — light and dark modes, plus Windows High Contrast.
motionlint review http://localhost:3000 --schemes --forced-colors --format html -o review.html
# Interaction affordances — grid each element's default/hover/focus/active states.
motionlint review http://localhost:3000 --state-grid
# Agent focus — keep only the top 5 findings, and only ones not seen in prior runs.
motionlint review http://localhost:3000 --max-findings 5 --new-only
# Before/after comparison — PR preview vs. production baseline.
motionlint review https://pr-123.preview.example.com --against https://prod.example.com
# Reviewer focus — cap the SARIF upload at 10 annotations per report.
motionlint review https://staging.acme.dev --format sarif -o ux.sarif --max-pr-annotations 10
# Pick a provider explicitly (auto-detect picks the first reachable one).
motionlint review http://localhost:3000 --provider anthropic --model claude-sonnet-5
# Track provider quality across runs + teach the reviewer from eval misses.
motionlint eval --provider anthropic --evolve
npm パッケージ:motionlint。
フローをレビューする際のターミナル出力例:
$ motionlint flow --spec flows/signup.json --provider anthropic
→ Running flow "signup-happy-path" against http://localhost:3000/signup (11 steps, 50ms intervals × 750ms window)
provider: anthropic (claude-sonnet-5)
capturing flow…
✓ step 1: 16 frames ✓ step 2: 16 frames ✓ step 3: 16 frames …
captured 176 frames in 31s
contact sheet → .motionlint/flows/signup-happy-path-…png
analyzing flow…
report → .motionlint/flows/signup-happy-path.md
Score: 4/10 · 3 critical findings
[critical] interaction — input focus rings missing across steps 2/4/6
[critical] interaction — submit button has no pressed state
[critical] loading_state — 1.4s wait with no spinner during submit
デモを試す
複数のルートを備えた TS アニメーションのショーケースが demo/ に含まれています。Motion One、GSAP、anime.js、@formkit/auto-animate、lottie-web を取り上げており、1 つの URL ですべての MotionLint 機能を試せる、猫をテーマにした 1 ページのデモもあります:
node demo/server.mjs # http://localhost:4173
motionlint review http://localhost:4173/cat --record --embed
motionlint flow --spec flows/signup.json
motionlint tune http://localhost:4173/dashboard
利用可能なルート:/、/pricing、/signup、/dashboard、/loading、/cat。レポートは .motionlint/reports/ に、スクリーンショットは .motionlint/screenshots/ に、動画は .motionlint/videos/ に保存されます。
セットアップ
API キー
MotionLint は起動時に、作業ディレクトリ内の .env ファイルを自動的に読み込みます:
# .env (gitignored)
ANTHROPIC_API_KEY=sk-ant-...
# or
OPENAI_API_KEY=sk-...
# or
GOOGLE_API_KEY=...
# or run a local Ollama (no key needed) — auto-detected on http://localhost:11434
実際の環境変数は .env より優先されます。キーが設定されておらず、Ollama も実行されていない場合、MotionLint は決定論的なモックプロバイダーにフォールバックします。これにより、スモークテスト用にパイプライン全体(キャプチャ → 分析 → レポート)がエンドツーエンドで実行されます。
プロバイダーの自動検出
MotionLint は次の順序でプロバイダーを自動検出します:Ollama(ローカル)→ Anthropic → OpenAI → Google。有効な API キーがある(またはサービスが実行中の)最初のプロバイダーが選択されます。--provider <name> と --model <id> で指定できます。プロバイダーごとの品質スコアカードと選び方については、プロバイダーの詳細をご覧ください。
以下は、MotionLint の内部の仕組みを理解したい方、ワークフローに合ったプロバイダーを選びたい方、または CI に組み込みたい方向けの内容です。
プロバイダーを横断した品質検証
flow-review パイプラインは、一般的なウェブアプリのアニメーションパターン12種類 × 2バリアント(フィクスチャ合計24件)でストレステストを実施しました。対象は、段階的な表示、ホバー/押下/フォーカス、モーダルの表示、ローディングスケルトン、フォームエラー、トースト、カウンターの増加、複数アニメーションを使うダッシュボード、コンテンツを段階的に表示するモーダル、豊富なフォームフィードバック(フォーカス+押下+スピナー+成功)、スクロール駆動アニメーション(プログレスバー+IntersectionObserver による表示+パララックス)です。
2026-07-27に、主要プロバイダー各社の現行フラッグシップモデルを使って実行しました。
| プロバイダー · モデル | 再現率(検出した不具合) | FPR(問題のないものへの誤検出) | スコア差 | 実時間 |
|---|---|---|---|---|
| OpenAI · gpt-5.6-sol | 100%(12/12) | 0%(0/12) | +3.3 | 10.9 min |
| OpenAI · gpt-5.5 | 100%(12/12) | 0%(0/12) | +3.3 | 11.5 min |
| Anthropic · claude-opus-5 | 100%(12/12) | 8%(1/12) | +4.1 | 21.0 min |
| Google · gemini-3.6-flash | 100%(12/12) | 17%(2/12) | +5.1 | 4.9 min |
| Anthropic · claude-sonnet-5 | 100%(12/12) | 33%(4/12) | +3.1 | 10.8 min |
次のように読み取ってください。再現率は、もはや差別化要因ではありません。 現行のフラッグシップモデルはどれも、仕込まれた不具合を12件すべて検出します。これが今回の検証結果です。1年前はそうではありませんでした。つまり、MotionLint が機能するかどうかは、もはやモデルの選択では決まりません。コストとレイテンシーで選んでください。
FPR の列でモデルを順位付けしないでください。 24件のフィクスチャを使った1回の実行では、差を判定できません。同一のスイートを条件を変えずにサンプリングだけ変えて2回実行したところ、FPR はモデルごとに1~2件のフィクスチャ分変動しました。gpt-5.5 は1/12 → 0/12、gpt-5.6-sol は2/12 → 0/12、gemini-3.6-flash は3/12 → 2/12でした。フィクスチャ1件で8パーセントポイントに相当するため、「0%」から「17%」までの差全体がノイズフロアの範囲内です。この列は順位ではなく、*「どのモデルも、問題のないものを誤検出することがある」*と捉えてください。
この表の過去の数値が誤っていた理由
このスイートを最初に実行した2026-07-27の結果では、claude-opus-5 の再現率は83%となり、5モデル中最下位でした。また、2026-04-29版のこの表では、複数のモデルのFPRが0%と報告されていました。どちらもモデルの挙動ではなく、MotionLint のバグによるものでした。
Anthropic の max_tokens はデフォルトで4096でした。冗長な応答は上限に達してJSONの途中で切れ、解析できない結果が 0/10, no issues found として採点されました。これは問題のないレビューと区別できませんでした。Opus 5の3件の応答切り詰めのうち2件は不具合のあるフィクスチャで発生し、83%という数値を生み出しました。
同じバグによって、すべてのモデルでFPRも低く見積もられていました。レビューが途中で切れると何も報告されないため、誤検出を増やせません。過去に「FPR 0%」とされた値は、モデルの精度だけでなく、解析の失敗も一部測定していました。この問題は2026-07-27に修正しました。あわせて、途中で切れた応答、拒否された応答、安全性フィルターでブロックされた応答を問題のない結果に見せていた関連経路も修正しました。
各プロバイダーの詳細なスコアカードは、scripts/run-all-benchmarks.mjs を実行した後に .motionlint/stress/ で確認できます。単一のモデルを再実行するには、--only <provider>:<model> を使用してください。
プロバイダーの詳細
| プロバイダー | モデル | セットアップ | 品質(24 件のフィクスチャ) | レビューあたりのコスト¹ |
|---|---|---|---|---|
google | gemini-3.6-flash | GOOGLE_API_KEY=… | 再現率 100% · FPR 17% · 差 +5.1 | $0.019 |
anthropic | claude-sonnet-5 | ANTHROPIC_API_KEY=… | 再現率 100% · FPR 33% · 差 +3.1 | $0.089 |
openai | gpt-5.5 | OPENAI_API_KEY=… | 再現率 100% · FPR 0% · 差 +3.3 | $0.248 |
openai | gpt-5.6-sol | OPENAI_API_KEY=… | 再現率 100% · FPR 0% · 差 +3.3 | $0.265 |
anthropic | claude-opus-5 | ANTHROPIC_API_KEY=… | 再現率 100% · FPR 8% · 差 +4.1 | $0.293 |
ollama | 任意のビジョンモデル | ollama serve + ollama pull <model> | 今回の実行ではベンチマーク未実施 | $0 |
mock | ヒューリスティックなスタブ | (自動フォールバック) | 該当なし — CI のスモークテスト用の決定論的なスタブ | $0 |
¹ 推定値ではなく実測値です — 各モデルでデモアプリに対して、デフォルトの 2 つのビューポートを使い、フルページで実際の motionlint review を 1 回実行しました。各プロバイダーの使用量フィールドから実際のトークン数を読み取り、公表されている定価を乗じています。任意の実行で formatUsageLine() を使って再現できます。Sonnet 5 には導入価格が適用されています(2026-08-31 まで)。その後はおよそ 1.5 倍になります。フローレビューではフローごとに 1 枚の合成画像を送信しますが、コンタクトシートはより大きくなります。Animation Tuner と motionlint audit は LLM を一切呼び出さず、コストもかかりません。
コストの大部分は出力トークンです。 入力は 5 モデル間で 2 倍以内ですが、出力は 1,390(Gemini)から 10,219(Opus 5)まで幅があります。最も高価なモデルが最も安価なモデルの 15 倍になるのは、画像サイズではなく、この 7 倍の差によるものです。
選び方
- デフォルト。 Google の
gemini-3.6-flash— 再現率 100% で、Opus 5 より13 倍安く、5 モデル中で最速です(4.9 分)。すべてのモデルがすべての不具合を検出したため、デフォルトで追加料金を払う品質上の理由はありません。 - Anthropic を標準採用する場合。
claude-sonnet-5は $0.089 で、claude-opus-5より 3 倍安く、再現率は同じです。Opus 5 はより高価で、実測した再現率に優位性がないにもかかわらず、実時間が2 倍かかりました(21.0 分対 10.8 分)。わずかに高いスコア差(+4.1 対 +3.1)を重視する場合にのみ選んでください。 - OpenAI を標準採用する場合。
gpt-5.5とgpt-5.6-solは、測定したすべての軸で差がなく、価格差も 7% 以内です。すでにアカウントで利用できる方を選んでください。 - 厳格な CI ゲート。 再現率を基準にすれば、どれでも問題ありません。FPR を基準に選ばないでください — 上記のノイズフロアに関する注意を参照してください。誤検知がゲートに影響する場合は、こちらの 24 件のフィクスチャによる単一実行をそのまま信頼せず、独自のフィクスチャを実行してください。
- ローカル/エアギャップ環境。 Ollama のビジョンモデルならどれでも動作しますが、ビジョン機能に対応していることを確認してください。API 経由で画像を受け付けても、画像を黙って無視し、プロンプトだけをもとに回答するモデルもあります。今回の実行ではいずれもベンチマークを実施していません。
プロバイダーの切り替え
すべてのコマンドで --provider と --model を使用できます。
motionlint review http://localhost:3000 --provider openai --model gpt-5.5
motionlint flow --spec flows/signup.json --provider google --model gemini-3.6-flash
motionlint review http://localhost:3000 --provider ollama --model llava:13b
独自のプロバイダーのベンチマーク
新しいプロバイダーを同じ 24 件のフィクスチャによるストレステストと比較するには、次のようにします。
node -e "
import('./dist/config/env.js').then(async ({ loadEnv }) => {
loadEnv();
const { runStress, renderStressMarkdown } = await import('./dist/flow/stress.js');
const { writeFile, mkdir } = await import('node:fs/promises');
const { resolve } = await import('node:path');
await mkdir('.motionlint/stress', { recursive: true });
const r = await runStress({
stressPath: resolve('eval/animation-stress.json'),
fixturesDir: resolve('eval/animation-fixtures'),
artifactDir: resolve('.motionlint/stress'),
provider: 'YOUR_PROVIDER', // 'openai' | 'google' | 'ollama'
});
await writeFile('.motionlint/stress/SCORECARD.md', renderStressMarkdown(r), 'utf8');
console.error('Recall:', (r.broken_recall*100).toFixed(0)+'%, FPR:', (r.good_false_positive_rate*100).toFixed(0)+'%, gap:', r.avg_score_gap.toFixed(1));
});
"
パターンごとの内訳は .motionlint/stress/SCORECARD.md を開いて確認してください。
motionlint flow の仕組み
静的なスクリーンショットでは、フローのアニメーションやインタラクション状態が機能しているかどうかはわかりません。最終フレームの見た目が正しいかどうかしか確認できません。motionlint flow はそのギャップを埋めます。
スクリプト化されたユーザージャーニーを指定すると、次の処理を行います。
- Playwright を介してヘッドレス Chromium でユーザージャーニーを実行します。ユーザーと同じように、クリック、入力、ホバー、スクロール、キー押下を行います。
- CDP のスクリーンキャスト(
Page.captureScreenshotJPEG、1枚あたり約8ms)を介して、各インタラクション後の750ms間に16フレーム(50ms間隔)を連続撮影します。50msは人間の視覚検出閾値の半分であり、業界で一般的なアニメーション間隔の最小値である100msを下回ります。そのため、100msのボタン押下のような短いアニメーションも、中間状態のフレームを2~3枚捉えられます。各インタラクションの連続撮影では、入力からフィードバックまでの遅延もピクセル差分で検出します。バースト期間内に視覚的な応答がないインタラクションは、決定論的にフラグ付けされます。 - 後からスクラブ再生できるアーティファクトとして、Playwright の動画全体を記録します。
- 各バーストをラベル付きのコンタクトシートに合成します。ステップごとに1行で、フレームは副行に配置されます。
- フローを考慮した評価基準とともにシートをビジョン LLM に送信します。評価基準には、アニメーションの欠落、アニメーションの不具合やカクつき、ローディング状態の欠落、体感パフォーマンス、アフォーダンスと状態変化、演出、滑らかさ、意図しないちらつき、ナビゲーションの連続性、モーション軽減への対応が含まれます。
- ステップごとのトレース、優先順位付けされた検出結果、末尾の **「Claude Code 用プロンプト」**ブロックを含む Markdown レポートを生成します。これを CC に貼り付けると、検出結果に直接対応します。
複数アニメーションの処理
1つの記録で、複数のアニメーションを同時に撮影し、分析できます。次のケースで検証済みです。
- ダッシュボードの表示(同時に3つ:タイルの段階表示+カウンターの段階的変化+チャートの棒の伸長)
- モーダルの重ね表示(背景のフェード+モーダルのスライドとフェード+内部コンテンツの段階表示)
- 詳細なフォームのフィードバック(フォーカスリング+ボタン押下+ローディングスピナー+成功カード)
- スクロール連動(スクロール進捗バー+IntersectionObserver によるセクション表示+ヒーローの視差効果)
LLM は、動作しているアニメーションを誤ってフラグ付けすることなく、どのアニメーションに不具合があるかを正しく特定します。検証済み品質の表を参照してください。
スクロール連動アニメーション
スクロール連動アニメーションのあるサイトでは、scroll <px> ステップによって、バースト期間中に requestAnimationFrame 経由でスクロールをアニメーションさせます。そのため、各フレームでスクロール位置が段階的に変化し、ページのスクロール中のタイミングを LLM が把握できます。
フローの例
# Inline DSL — semicolon-separated steps
motionlint flow \
--url http://localhost:3000 \
--steps "navigate /signup; click input#email; type input#[email protected]; click button[type=submit]; wait 2000; capture \"post-submit\"" \
--name signup-happy-path
# Or load a structured spec with expected_animations[] hints
motionlint flow --spec flows/signup.json --provider anthropic
# Pass team motion preferences (philosophy + inspirations + accepted defaults)
# Embedded into the prompt AND the report's CC handoff block.
motionlint flow --spec flows/signup.json --preferences flows/preferences.md
# Tighten the interval below 50ms for fine-grained timing review
motionlint flow --spec flows/signup.json --interval 30 --burst-ms 600
# Auto-detect: scan the page's animations, pick an interval that captures
# the shortest one with 4 frames inside it (clamped to [20, 100]ms).
motionlint flow --spec flows/signup.json --auto-interval
インライン DSL リファレンス
| アクション | 形式 | 備考 |
|---|---|---|
| navigate | navigate /pricing | パスまたは完全な URL |
| click | click button#start | CSS セレクター |
| hover | hover .feature | CSS セレクター |
| type | type input#[email protected] | セレクター=値 |
| press | press Enter | キー |
| scroll | scroll 800 | ピクセル数。バースト期間中にアニメーションします |
| wait | wait 500 | ms |
| capture | capture "post-submit" | 任意のラベルを付けて明示的にバーストを撮影します |
デフォルトでは、すべてのインタラクション後にフレームのバーストを撮影します。明示的な capture ステップの場合のみバーストを撮影するには、--no-implicit-bursts を指定します。動画の記録を省略するには、--no-record を指定します。
すぐに実行できるサンプルフローが3つ、リポジトリに含まれています。flows/signup.json、flows/loading-state.json、flows/preferences.md。
アニメーションチューナーの仕組み
ほとんどの AI コーディングツールは、アニメーションを一から生成します。チューナーを使うと、ページ上ですでに動作しているアニメーションをリアルタイムで調整し、その変更を構造化されたプロンプトとしてコーディングエージェントに渡せます。
motionlint tune http://localhost:3000 --open
次の処理を行います。
- 主要な TS アニメーションライブラリ(Motion One、GSAP、anime.js、@formkit/auto-animate、lottie-web)に加え、ページ上で実行されているすべての CSS トランジションと
@keyframesをフックする計測スクリプトを使って、ヘッドレス Chromium でアプリを開きます。 - 検出されたアニメーションをすべてキャプチャします。対象要素のセレクター、ソースライブラリ、タイミングパラメーター、バウンディングボックスが含まれます。
- 自己完結型のインタラクティブな HTML ページを
.motionlint/tuner/index.htmlに生成します(--openを指定すると自動で開きます)。- アニメーションごとのライブプレビュー領域(Shadow DOM — iframe もちらつきもなく、ソースページのテーマを適用)。
- 継続時間/遅延/スタガー/速度を調整するスライダー。
- イージングプリセットのドロップダウン — Emil Kowalski の力強いカーブ(ease-out、ease-in-out、iOS ドロワー)が先頭に並び、その後に穏やかで装飾的なオプションが続きます。
- インラインの標準準拠チェック — 各カードで、アニメーションがモーション標準から外れている箇所を表示します(重大度バッジ、修正方法、推奨値)。ヘッダーにはスコアも表示されます。
- デザインの意図を記録できる、アニメーションごとのコメント欄。
- Markdown ファイルと、構造化された
changes[]JSON ブロックを含む Claude-Code 対応プロンプトをエクスポートします。これを CC に貼り付けると、コードベースが編集され、新しいパラメーターが適用されます。
$ motionlint tune http://localhost:3000
→ Capturing animations on http://localhost:3000…
detected 15 animation(s)
tuner → /Users/you/proj/.motionlint/tuner/index.html
open with: file:///Users/you/proj/.motionlint/tuner/index.html
アニメーション標準 — motionlint audit
MotionLint は、Emil Kowalski のデザインエンジニアリング標準を決定的なリンターとして実装しています。ビジョンモデルも API キーもコストも必要ありません。motionlint audit はページを計測し、各アニメーションで実際に使われているタイミング、イージング、変形の値を読み取り、評価します。
| カテゴリ | 検出する問題 | 標準 |
|---|---|---|
| イージング | UI での ease-in、意図的な登場アニメーションでの弱い組み込みカーブ | 登場/退出には強い ease-out cubic-bezier(0.23, 1, 0.32, 1) を使用し、ease-in は使わない |
| 継続時間 | モーダル/ドロワーの 200~500ms は除き、300ms の上限を超える UI モーション | 180ms のトランジションは 400ms よりきびきびと感じられます。退出は約 20%速くします |
| 物理感 | scale(0) から始まる登場アニメーション | 何もないところから出現させず、scale(0.95) と opacity: 0 から始めます |
| パフォーマンス | transition: all、レイアウトプロパティのアニメーション、不要な無限ループ | transform と opacity のみをアニメーションさせます。これらはレイアウトとペイントをスキップします |
| 一貫性 | 手作業で作られたイージングカーブの乱立、30~80ms の範囲外のスタガー間隔 | カーブと継続時間は共有トークンとして定義し、グループ化された登場アニメーションは 30~80ms 間隔でずらします |
| 継続時間(ペア) | 対応する登場アニメーションより退出アニメーションが速くないケース(fadeIn 300ms/fadeOut 300ms) | 退出は対応する登場アニメーションより約 20%速くします |
motionlint audit http://localhost:3000 --open # polished HTML report, scored 0–100
motionlint audit http://localhost:3000 --json audit.json --ci # machine-readable; non-zero on critical
--layout を追加すると、ライブ DOM の計測値に基づいてレイアウト(タップ領域、文字サイズ、コントラスト、オーバーフロー)もチェックします。引き続き決定的で、API キーも不要です。
--watch [dir] を追加すると、[dir](デフォルト:cwd)以下のファイル変更時に監査を再実行し、実行ごとにスコアとその変化を表示します。反復作業中に、結果をリアルタイムで確認できます。再帰的な監視には、macOS、Windows、または Node 20 以降の Linux が必要です。
レポートでは、各指摘事項を変更前 → 変更後のパネルと並べて表示します。イージングに関する指摘では、cubic-bezier カーブをライブで比較できるため、修正内容を説明だけでなく目で確認できます。同じ標準は flow のレビュー用プロンプトにも使われるため、ビジョンによる指摘が具体的なルールに基づくものになります。また、アニメーションチューナーにもインラインで表示されます。
MCP サーバー — ツール、リソース、デプロイ
MotionLint は stdio 経由の MCP サーバーを提供しており、LLM エージェントがチャット内から直接操作できます。motionlint mcp サブコマンドで起動し、ツールが呼び出されるとエージェントのクライアントがプロセスを生成します。
Claude Code へのインストール
公開済みの npm 版(推奨):
claude mcp add motionlint -- npx -y motionlint mcp
ローカルのチェックアウト版(開発中に便利):
claude mcp add motionlint -- node /absolute/path/to/motionlint/dist/index.js mcp
登録後:
- 一覧に表示されることを確認します:
claude mcp list—motionlintがrunningまたはavailableと表示されるはずです。 - API キーにアクセスできることを確認します。MCP サーバーは、起動元から環境変数を引き継ぎます。最も簡単な方法は、作業中のプロジェクトディレクトリに
.envファイルを配置することです。MotionLint は起動時に自動で読み込みます。 - 初回実行時:まだ実行していない場合は、
npx playwright install chromiumを実行します。
続いて、Claude Code で:
"motionlint を使って、ローカルアプリをモバイルとデスクトップでレビューし、修正すべき主な問題を上位 3 件教えてください。"
"
http://localhost:3000/signupで、手順click input#email; type input#[email protected]; click button[type=submit]; wait 2000; captureを使って motionlint review_flow を実行し、アニメーションを確認してください。""
http://localhost:3000/pricingで motionlint tune_animations を実行してください。カードのホバーアニメーションを微調整したいです。"
公開されるツール
| ツール | 機能 |
|---|---|
review_url(url, viewports?, provider?, model?, wait_for?, record?, format?, max_findings?, max_pr_annotations?, new_only?) | 複数のビューポートで URL の静的 UX レビューを行います。Markdown/JSON/SARIF 形式のレポートを返します。 |
review_routes(base_url, routes, viewports?, ..., max_findings?, max_pr_annotations?, new_only?) | 1 つのアプリの複数ルートで同じレビューを行います。 |
review_flow(url, steps?|spec_path?, preferences_path?, provider?, ...) | スクリプト化されたユーザージャーニーのアニメーション/インタラクションレビューを行います。構造化された CC ハンドオフブロックを含むフローレポートを返します。 |
tune_animations(url, viewport_*?, settle_ms?, output?) | ページ上のすべてのアニメーションを検出し、操作可能な HTML チューナーを書き出します。ファイルパスを返します。 |
get_latest_report(format?) | 最新のレビュー/フローレポートの内容を返します。 |
リソース:motionlint://reports/latest — 最新のレポートの内容です。
デプロイのチェックリスト
MCP サーバーをデプロイする前、または他のユーザーと共有する前に確認してください。
- ビルドが最新であること。
npm run buildを実行し、dist/index.jsが存在することを確認します。これを行わないと、motionlint mcpは起動しません。 - Playwright Chromium が対象マシンにインストールされていること:
npx playwright install chromium。postinstall フックで通知されますが、必須ではありません(npm install時に 300 MB のバイナリを自動ダウンロードすることはありません)。 - API キーにアクセスできること — シェルの環境変数を使うか、MCP クライアントの起動元となる作業ディレクトリに
.envファイルを配置します。 - MCP の機能をスモークテストすること。
npm testには、サーバーを起動してツールを一覧表示し、想定されるツール構成を検証する MCP スモークテストが含まれています。 - シークレットがコミットされていないこと。
.envは gitignore 対象です。.env.exampleはプレースホルダーにしてください。プッシュ前に最後にgit diff --cached | grep -i 'sk-\|api_key'を実行しておくとよいでしょう。 -
claude mcp listで確認すること: サーバーが表示され、起動時にエラーが発生していないことを確認します。
CI 連携
# .github/workflows/ux.yml
- run: npm ci
- run: npx playwright install chromium
- run: npx motionlint review $STAGING_URL --ci --threshold critical --format sarif -o ux.sarif
- uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: ux.sarif }
クリティカルな問題が設定されたしきい値(failOnCritical)を超えると、MotionLint は 1 で終了します。これをステータスチェックとして設定してください。
キャプチャ対象・分析内容
キャプチャ対象:
- デフォルトの3つのビューポート(モバイル 375/タブレット 768/デスクトップ 1440)でのページ全体のスクリーンショット。設定で変更できます。
--no-full-pageを指定した場合のファーストビューのスクリーンショット。--recordを指定した場合の、ナビゲーションとキャプチャの実行を記録した動画(Playwright の.webm)。- キャプチャ前に実行するインタラクションのシーケンス:
click、hover、type、scroll、wait。 - 認証状態:Cookie、
localStorage、beforeNavigateスクリプト。すべて.motionlintrc.jsonで設定できます。
motionlint flow のコンタクトシート。各インタラクション後のタイムスタンプ付きバースト画像で、ビジョンモデルに表示される内容をそのまま示しています。
分析内容: 各スクリーンショットを、12の観点(hierarchy、spacing、alignment、typography、color、contrast、responsiveness、interaction、content、navigation、consistency、loading_state)を網羅した、独自のUXレビュープロンプトとともにビジョンモデルに送信します。モデルは各問題について次の内容を返します。
{
"category": "hierarchy",
"severity": "critical | warning | suggestion",
"location": "above-the-fold hero",
"issue": "Primary CTA blends into the background gradient.",
"why_it_matters": "Users miss the conversion path on first scroll.",
"fix": "Increase background contrast or use a solid surface behind the button."
}
--rules path/to/your-design-rules.md を指定すると、プロジェクト固有のヒューリスティクスを組み込むためにプロンプトを上書きできます。
レビュー用のキャプチャでは毎回DOMスナップショットも取得します。見出し、CTA、入力欄などの注目すべき要素には、計測したピクセル単位の矩形とともに、安定した参照ID(E1、E2、…)が割り当てられ、プロンプトに一覧表示されます。モデルはこれを根拠として、指摘に "element_ref": "E3" を指定できます。参照されたIDは対応する矩形に解決され、HTMLレポートのスクリーンショット上に重要度別の色付きバウンディングボックスとして描画されます(Markdownでは Where: E3 at (x, y) w×h として報告されます)。ページに表示されていない参照IDは除外されます。モデルに提示されていない要素には注釈を付けられません。
--format html を指定すると、指摘が共有可能な単一のレポートとして表示されます。スコアリング、観点別の内訳、各指摘に対する問題と修正案のパネル、注釈付きスクリーンショットが含まれます。
設定リファレンス
リポジトリのルートに .motionlintrc.json を配置してください(または motionlint.config.js、package.json 内の "motionlint" キーを使用してください)。
{
"provider": "auto",
"fallbackProvider": "anthropic",
"fallbackModel": "claude-sonnet-5",
"viewports": {
"mobile": { "width": 375, "height": 812 },
"tablet": { "width": 768, "height": 1024 },
"desktop": { "width": 1440, "height": 900 }
},
"defaultViewports": ["mobile", "desktop"],
"waitFor": "networkidle",
"waitTimeout": 10000,
"screenshotDir": ".motionlint/screenshots",
"videoDir": ".motionlint/videos",
"reportDir": ".motionlint/reports",
"rules": null,
"record": false,
"maxFindings": null,
"maxPrAnnotations": null,
"memory": {
"enabled": true,
"path": ".motionlint/memory.json",
"baseline": ".motionlintignore",
"newOnly": false
},
"resources": { "maxConcurrentReviews": null, "providerCallsPerMinute": null, "maxTokensPerRun": null },
"ci": { "threshold": "warning", "failOnCritical": true },
"auth": { "cookies": null, "localStorage": null, "beforeNavigate": null }
}
レビュー量の制御
同じルートでレビューを再実行すると、毎回同じ指摘が表示されていました。出力を重要な内容に絞るため、次の 2 つの仕組みを用意しています。
- 実行ごとの出力上限 —
--max-findings N(または設定のmaxFindings)を指定すると、実行ごとの指摘を重要度順に上位 N 件に絞り込めます。これにより、エージェントは最も重要なものから対応できます。レポートのOmitted行には、上限により除外された件数が表示されます。 - PR 表示上限 —
--max-pr-annotations N(または設定のmaxPrAnnotations。SARIF のみ)を指定すると、レポートごとの結果を重要度順に最大 N 件まで出力できます。これにより、コードスキャンのアップロードで PR に注釈があふれるのを防げます。除外された件数は、SARIF の実行プロパティomitted_by_pr_capに記録されます。 - リソース上限 —
resources.maxConcurrentReviewsは、1 つのプロセス内で同時に実行するレビュー数(複数のエージェントからのレビューに対応する MCP サーバーなど)を制限します。また、resources.providerCallsPerMinuteは、ビジョン LLM の呼び出しに対するプロセス全体のスライディングウィンドウ上限です(プロバイダーの割り当て量/コストを制御します。また、flowレビューにも適用され、各--consistencyサンプルがカウントされます)。どちらもデフォルトでは無制限で、設定ファイルでのみ指定できます。なお、これらは組み合わせて適用されます。つまり、同時実行枠を使用しているレビューもレート制限を待つため、両方の値を厳しくすると、遅延が相乗的に大きくなります。 - コスト上限 — すべてのプロバイダー呼び出しのトークン使用量を取得し、実行ごとに合計します(レポートの
Tokens:行、SARIF の実行プロパティtoken_usage)。--max-tokens N(または設定のresources.maxTokensPerRun)を指定すると、実行ごとのトークン予算を設定できます。累計がこの上限を超えると、残りのビューポートはスキップされ、レポートのskipped_viewportsに記載されます。使用量を報告しないプロバイダーの呼び出しも件数には含まれますが、予算は消費しません。 - 実行間の記録 — 各指摘には安定した ID(カテゴリ、要素の位置、正規化された問題文のハッシュ)が付与されます。再発の検出では、単純なハッシュ一致よりも踏み込んでいます。カテゴリの類義語の互換性と正規化トークンの重複度(実際の実行間データで調整したしきい値)をもとに、ビジョン LLM が実行ごとに言い換えても同じ問題を照合します。検出された回数は
.motionlint/memory.jsonに URL ごとに記録され、再発した指摘には黙って除外するのではなく、過去 N 回の実行で検出 と注記されます。差分のみを表示するには--new-onlyを指定します。指摘を恒久的に無視するには、その ID を.motionlintignoreにコピーします(1 行に 1 つのハッシュを記述し、#コメントや末尾の注記も使用できます)。すべての機能を無効にするには--no-memoryを指定します。
SARIF 出力には指摘 ID が partialFingerprint として含まれるため、GitHub コードスキャンは同じ指摘を実行や PR をまたいでネイティブに重複排除します。
同じプロジェクトのレビューを同時に実行しても安全です。記録された検出回数が並行実行によって上書きされないよう、古いロックを検出できるファイルロック(memory.json.lock)を使ってメモリストアを更新します。ロックが解除されなくてもレビューが失敗することはありません。短時間待機した後、警告を表示してロックなしで続行します。
ユースケース
- マージ前の UX ガードレール。 デザイナーがいない個人開発者や 2 人のスタートアップ向けです。CI で
motionlint review https://pr-123.preview.example.com --ci --threshold criticalを実行すると、少なくとも問題を確認するまで、警告以上の指摘がマージをブロックします。 - Claude Code 内の MCP デザインパートナー。 MotionLint を MCP サーバーとして追加し、CC に 「ローカルアプリをモバイルとデスクトップでレビューして、修正すべき上位 3 件を教えてください」 と尋ねます。CC がツールを操作し、同じ会話内で注釈付きフィードバックを返します。
- 継続的な品質モニタリング。 夜間 cron を設定し(
motionlint review https://prod.example.com --format sarif -o ux.sarif)、コードスキャンのダッシュボードに SARIF を表示することで、本番環境でのリグレッションを翌朝に検出できます。 - リリース直後の機能に対するアニメーション/フローの QA。
motionlint flowは Playwright で人間のようにスクリプト化されたユーザージャーニーを実行し、各インタラクションで連続フレームをキャプチャして動画を記録し、キャプチャしたフレームをもとに LLM に アニメーションの動作 をレビューさせます。 - アニメーションのライブ調整と Claude Code への引き継ぎ。 ページ上のすべてのアニメーションをキャプチャし、スライダーでタイミング/イージング/遅延をライブ調整して、CC が直接実行できる構造化プロンプトをエクスポートします。
プロジェクトの構成
src/
capture/ Playwright capture (screenshot, mosaic, DOM snapshot) + interaction sequences
providers/ Vision LLM providers (ollama, anthropic, openai, google, mock) + self-consistency wrapper
analysis/ Rubric-style UX prompt + JSON parser + rule injection
report/ Markdown / JSON / SARIF report generators
eval/ Tiered eval harness (L1/L2/L3 fixtures, scorer, runner, report)
flow/ Flow runner — spec parser, capture orchestrator, animation-aware report
tuner/ Animation Tuner — extractor, instrumentation script, Shadow-DOM render
mcp/ MCP server for Claude Code
cli/ Commander.js commands + terminal output
config/ cosmiconfig loader + .env loader
demo/ TS animation showcase used as a review target
flows/ Sample flow specs (signup, loading-state) for `motionlint flow`
eval/fixtures/ Labelled HTML pages with seeded UX faults at three complexity levels
test/ Node test runner unit + integration tests
ロードマップ
v0.1(今回のリリース) — リリース済み:
- 3 つの CLI コマンド:
review、flow、tuneと MCP サーバー(motionlint mcp)。 - 5 つのビジョンプロバイダー:Anthropic、OpenAI、Google、Ollama、mock。
- モザイクキャプチャ、DOM 計測のサイドチャネル、自己一貫性サンプリング、同義語グラフを用いたソフトキーワードスコアリングに対応した、複数ビューポートの静的レビュー。
- 21 件のラベル付きフィクスチャと、後続の LLM コーディングツール向けの構造化された
next_actions[]JSON を備えた、段階的な評価ハーネス(L1/L2/L3)。 - CDP スクリーンキャストによる フレーム間隔 50ms のフローレビュー(750ms のバーストで 16 フレーム)、複数アニメーションとスクロール連動に対応。
- Shadow DOM プレビュー、ライブスライダー、イージングプリセット、Claude Code 向けエクスポートを備えた Animation Tuner。
- 12 パターンにわたる 24 件のフィクスチャで、再現率 100%/FPR 0% を検証したアニメーションストレステストハーネス。
- LLM の評価基準と CC への引き継ぎブロックに埋め込まれる、チームのモーション設定 Markdown(
--preferences)。 - ページ上で検出された最短アニメーションに基づいてフレーム間隔を選ぶ、自動間隔スキャン(
--auto-interval)。 - GitHub コードスキャン向けの SARIF 出力。
v0.2(進行中) — これまでにリリース済み:
- トークン使用量の記録と実行ごとのコスト上限(
--max-tokens/resources.maxTokensPerRun。すべてのレポートにTokens:行を表示)。 - ルートの自動検出(
--discover-routes:sitemap.xml と Next.js の app ディレクトリ)。 - 注釈付きバウンディングボックス:プロンプト内の DOM 要素参照、HTML レポート内のスクリーンショットへの指摘の描画。
- インタラクション状態グリッド(
--state-grid:要素ごとに default/hover/focus/active を 1 枚のラベル付き画像に表示)。 - モデルごとのリグレッション検出に対応したプロバイダーのスコアカード履歴(
.motionlint/eval-history.json)。 - 評価の
next_actionsによるクローズドループのプロンプト改善(eval --evolve→ レビュープロンプトに学習済みヒューリスティクスを適用)。 - 監査ルールを 2 つ追加:スタガー間隔の範囲(30~80ms)と、退出を進入より約 20% 速くするルール。
v0.2(次期予定):
- GitHub Action ラッパー(
motionlint-action)。
謝辞
MotionLint は、他の方々の成果を基盤としています。
- Emil Kowalski —
motionlint auditのアニメーション基準、チューナーのイージングプリセット、フローレビューの評価基準は、彼のデザインエンジニアリングに関する執筆と、animations.dev のコースから要点をまとめたものです。彼のオープンソース UI ライブラリである sonner(トースト)と vaul(ドロワー)は、これらのルールが説明するモーションの、生きた参照実装です。MotionLint は独立したプロジェクトであり、Emil との提携や、Emil による推奨を受けているものではありません。 - ctx(ctx.rs) — ローカルのコーディングエージェントの履歴検索ツールです。エージェントの実行をまたいで調査結果がどのように保持される(あるいは失われる)のかを調べるため、実行間メモリレイヤーの開発中に使用しました。これらの実験は、調査結果 ID とベースラインの設計に直接反映されています。
ライセンス
MIT © Resila Technologies Inc.
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。