Communitygithub.com

nikserg/skim

Skimのランディングページ用デモ動画とインターフェーススクリーンショットを、`demo/`内のモックデモハーネスから再生成します。Skim UIが変更され、ランディングアセットを更新する必要があるときに使用します。

skim とは?

このスキルは、SkimアプリケーションのUI変更に合わせて、ランディングページに同梱される製品デモ動画とライト/ダークテーマのスクリーンショットを自動再生成します。実際のアカウントやメールボックスにアクセスせず、モック化されたTauri IPCレイヤー(`demo/mock/`)上で実際のSkim UIを動作させるため、安全に実行できます。出力はすべて`docs/`ディレクトリに配置され、スクリプト化された機能ツアー動画(1280×800)と2枚のインターフェーススクリーンショット(800px幅)が含まれます。このスキルはファイルの更新のみを行い、Gitのコミットやプッシュは行いません。ユーザーは生成されたアセットを確認し、手動で保持するかどうかを決定します。また、デモの一部のみ(スクリーンショットのみ、または動画のみ)を個別に実行することも可能で、環境変数によるペーシング調整にも対応しています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/nikserg/skim/tree/HEAD/demo/skill

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Skimデモアセットの更新

ランディングページに同梱される製品デモ動画とライト/ダークのインターフェーススクリーンショットを再生成します。すべては実際のSkim UIをモック化されたTauri IPCレイヤー(demo/mock/)上で動作させることで駆動されるため、実際のアカウント、メールボックス、モデルに触れることは一切ありません。

出力はすべてdocs/に公開されます:

  • skim-demo.mp4 — スクリプト化された機能ツアー(1280×800)
  • skim-light.jpg、skim-dark.jpg — インターフェーススクリーンショット、800px幅

コミットやプッシュは行わないでください

このスキルはディスク上のファイルのみを更新します。git add、git commit、git pushを実行しないでください。ユーザー自身が再生成されたアセットを確認し、保持するかどうかを決定します。これらは大きな差分を生むバイナリファイルであり、終了コードが正常でも視覚的に間違っている可能性があります。ワーキングツリーをダーティなままにしておくことが正しい結果です。

ユーザーが同じリクエスト内で明示的にGit操作を依頼した場合(例:「再生成してコミットしてください」)にのみGitに触れてください。それ以外の場合は、ファイルが更新され、ステージングされていないことをユーザーに伝えて終了してください。

実行方法

リポジトリルートから:

npm run demo

これにより、3つのステップが連鎖的に実行されます: demo:record(Playwrightが実際のUIを操作しdemo/output/raw.webmを生成)→ demo:encode(ffmpegでMP4に変換しdocs/にコピー)→ demo:shots(両テーマのスクリーンショットをdocs/に生成)。

UIの一部だけが変更された場合は、必要な部分だけを実行してください。その方が高速で、関連のないアセットをバイト単位で同一に保つことができます:

  • npm run demo:shots — スクリーンショットのみ(静的UI、色、レイアウト変更)
  • npm run demo:record && npm run demo:encode — 動画のみ(フロー、AI動作)

前提条件: npm installが実行済みであり、ffmpegがPATHに含まれていること。全体の実行には数分かかります。録画が最も時間がかかる部分です。

npm run demoはdemo:browser(playwright install chromium)から始まります。ブラウザが既に存在する場合は何も実行しません。実行時に「Executable doesn't exist at ...chromium_headless_shell-NNNN」というエラーが発生した場合、それはPlaywrightのブラウザビルドがライブラリバージョンと一致していないことを示します(^のバンプで再解決され、ヘッドレスシェルはChromiumとは別のダウンロードです)。npm run demo:browserまたは完全なnpm run demoを実行すると解決します。デモの問題としてデバッグする必要はありません。個別のdemo:record / demo:shotsスクリプトはこのチェックをスキップします。

成功を報告する前に確認する

実行が終了コード0で終了しても、壊れた動画が生成される可能性があります。未処理のモックコマンドはエラーをスローする代わりにundefinedを返すため、エラーではなく空のペインとして表示されます。そのため、終了コードではなく目視で確認してください。

  1. docs/内の3つのファイルの更新日時が新しいことを確認します。
  2. サイズを確認します: スクリーンショットは800px幅、MP4は1280×800。
  3. MP4全体からフレームを抽出し、実際に目視確認します。固定秒数ではなく割合でサンプリングしてください。ツアーの長さはシーンが追加されたりペーシングが調整されたりすると変化するため、ハードコードされたタイムスタンプはすぐに使えなくなります:
    dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 docs/skim-demo.mp4)
    for k in 1 2 3 4 5 6 7; do
      ffmpeg -y -hide_banner -loglevel error \
        -ss $(echo "$dur * $k / 8" | bc -l) -i docs/skim-demo.mp4 -frames:v 1 /tmp/f$k.png
    done
    
    すべてのフレームにデータが表示されたペインが含まれ、AIシーンにはストリーミングされたテキストが表示されている必要があります。demo/output/progress.logには各シーンが終了した時点の名前が記録されており、問題のあるフレームを生成したステップを特定するのに役立ちます。
  4. 両方のスクリーンショットを表示します。特にダークテーマのものを確認してください(メール本文はサンドボックス化されたiframe内でレンダリングされ、独自のテーマロジックを持つため、ダークオン・ダークになる可能性があります)。

どのファイルが変更されたか、何を確認したかを報告します。シーンがおかしい場合は、そのまま出荷せずに修正してください。

UI変更後にツアーが壊れた場合

ハーネスは2つの契約に依存しています。失敗メッセージにより、どちらの契約が変更されたかがわかります:

IPCコマンド名(demo/mock/tauri-core.ts)。モックはsrc/lib/api.tsを反映したコマンド名のswitchでinvoke()を実装しています。コマンドがリネームまたは追加された場合は、対応するcaseを追加してください。症状: クラッシュではなく、空のペインまたはデータ欠落。

セレクタと英語ラベル(demo/record.mjs)。ツアーは.row、.quick-btn:has-text("Summarize")、.ai-input .instructionなどの要素をクリックします。CSSクラスのリネームやsrc/lib/i18n/locales/en.jsonの文字列変更により、マッチングステップが壊れ、タイムアウトエラーに失敗したセレクタの名前が表示されます。デモはlocale: "en"を強制するため、英語ラベルのみが重要です。

フィクスチャについても同様です。demo/mock/data.tsはai.prompt_*文字列と照合して、クイックプロンプトに対してどのスクリプト化された回答を返すかを決定し、ツアーはそれらの回答内の特徴的な単語("sync"、"yours"、"4.2")を待機します。フィクスチャの文言を変更すると、それに依存する待機がタイムアウトします。

すべてのフィクスチャデータとすべてのスクリプト化されたAI応答はdemo/mock/data.tsにあります。デモで別の内容(異なるメール、異なる要約、異なる下書き返信)を表示したい場合に編集するファイルです。

record.mjsを編集する際に注意すべき非自明な点:

  • コンポーザー本文は<textarea>です。ストリーミングされたコンテンツはそのvalueであり、テキストではありません。waitTextではなくwaitValueで待機してください。
  • .compose-window textareaはAI指示ボックスにもマッチします(DOM内で先に来ます)。本文には.compose-window > textareaを使用してください。
  • 作成シーンはハッシュでナビゲートし、その後にpage.reload()を呼び出す必要があります。ハッシュのみのgotoではSPAが再マウントされず、コンポーザーが表示されません。
  • 動画はbrowser.close()の前にvideo.saveAs()で保存してください。そうしないと「target closed」エラーで失敗します。

ペーシングとテーマ

デフォルトは読みやすいランディング動画向けに調整されています。実行ごとに環境変数(すべてミリ秒)で上書きできます: DEMO_READ(画面ごとの表示時間)、DEMO_BEAT(アクション間の間隔)、DEMO_TYPE(キーストローク遅延)、およびDEMO_AI_TYPING / DEMO_AI_THINK / DEMO_AI_STEP(AIストリームのテンポ)。コンテンツを追加した後にシーンが急ぎ足に感じられる場合に便利です。

テーマは2軸です — "<cold|warm>-<light|dark>"、例: warm-light(アプリのデフォルト)。両スクリプトはlocalStorage(skimdemo.theme)を通じてテーマを強制し、モックはget_settingsからそれを返します:

  • 動画はwarm-lightに固定されています。DEMO_THEME=cold-dark npm run demo:recordで上書きできます。
  • スクリーンショットはwarm-light → docs/skim-light.jpg、warm-dark → docs/skim-dark.jpgとしてレンダリングされます(demo/screenshots.mjsのSHOTS配列がテーマをファイル名にマッピングします)。

従来の単軸値("light"、"dark")には注意してください。これらは依然として解析されますが、coldパレットにマッピングされるため、エラーにならずに誤った温度でレンダリングされます。

DEMO_PREBUILT=1は、開発サーバーの代わりにdemo/dist-demoの静的ビルドを提供します。リソースが制限された環境やヘッドレス環境で便利です。

詳細はdemo/README.mdにあります。

関連スキル