/github-year-in-review
あなたの GitHub での 1 年を、投稿可能な 45 秒の動画にします。
姉妹スキルは /brag です。brag はプロジェクトをローンチ動画に変えるのに対し、これは個人の 1 年を動画に変えます。同じレンダリングパス (HyperFrames)、同じ配信方法 (フレーム 0 にポスターを焼き付け、シェアコピーも出力)。違いは、ストーリーがデータであるため、データとビートロジックがスクリプトとして同梱されており、エージェントの仕事は数字の確認、コピーの洗練、フレームの確認、そして納品を行うことです。
呼び出し方
/github-year-in-review
/github-year-in-review --user octocat --year 2025
/github-year-in-review --include-private --no-music
| オプション | デフォルト値 |
|---|---|
--user | 認証済みの gh ユーザー |
--year | 現在の年 (12 月 31 日までは "so far" と表示) |
--tz | このマシンのタイムゾーン (時間帯のビートで使用) |
--include-private | オフ: プライベートリポジトリはカウントされるが名前は表示しない |
--no-music | トラックがあれば音楽をオンにする |
--format | portrait 1080x1350 (唯一の出力形式) |
出力先はカレントディレクトリの year-in-review-<user>-<year>/ です (既に存在する場合はタイムスタンプを追加)。<skill-dir> はこのファイルが置かれているディレクトリです。
必要条件
gh 認証済み (gh auth status)、Python 3.9+、Node 18+ ( npx hyperframes 使用可能)、ffmpeg。
HyperFrames のドメインスキル (hyperframes-core、hyperframes-cli) でチェックとレンダリングを行います。
ステップ 1: 収集
python3 <skill-dir>/scripts/collect.py --user <login> --year <year> --out <out>/year.json
アクティブなアカウントで約 2 分かかります (クロックビート用にコミット履歴をサンプリングします)。合計、日別カレンダー、リズム (ストリーク、時間帯、曜日)、トップリポジトリ、言語、プルリクエスト、新規リポジトリ、年間獲得スター数、そして 自動化: サンプリングされたコミットのうち 60% 以上が同じメッセージテンプレートを共有するリポジトリ (ユーザーとしてコミットする cron) を書き出します。自動化はリズムや「成果」ビートからは除外され、独立したサプライズビートになります。
また、オプションの話題データも収集します: エージェント (コーディングエージェントと共著したコミット。署名からのみ検出。さらに、フッター、アプリ作成者、claude/ スタイルのブランチプレフィックスによるエージェント PR)、今年タグ付けされた リリース、および最大のマージ済み PR。これらは、該当データがある場合にのみビートになります (閾値は references/story.md 参照)。
ゲート: year.json を読み込み、ビルド前に正気性チェックを行ってください。ヘッドラインの合計は、その年のユーザーの GitHub プロフィールの数値と一致する必要があります。何かおかしい場合 (検出器が見逃したボット、名前を出すべきでないリポジトリなど) は、コレクターを修正するか story.json のオーバーライドを使用してください。数値をコンポジションに手動で編集しないでください。
ステップ 2: ストーリー
python3 <skill-dir>/scripts/build.py <out>/year.json --out <out> \
[--music <track.mp3> --cues <track.music-cues.json>]
これにより、<out>/story.json (ビート、コピー、タイミング)、<out>/composition/ (動画)、<out>/thumbnail/ (クローズの 1 秒静止画。カバー用。ステップ 4 参照) が書き出されます。ビート、そのデータ、およびフォールバックは references/story.md にあります。データの薄いビートは脱落するため、活動が少ない年は空の動画ではなく短い動画になります。
次に story.json を読み、デフォルトよりも具体的にできる箇所 (キャプション、アーキタイプ名とその理由、成果ビートの引用) のコピーを改善してください。ルール:
- すべての主張は
year.jsonの事実に基づいていなければなりません。架空の数字、データが裏付けない最上級表現は禁止。 - 短い行。タイプは意図的に大きく設定されています。約 12 語を超えるものは十分な時間表示されません。
--include-privateがない限り、プライベートリポジトリ名は禁止。- 絵文字、ダッシュ、"crushing it" のような口調は禁止。LinkedIn に投稿されるものです。
- エージェントと自動化は、その人が指揮したチームとして描くこと ("shipped with"、"co-written with")。決して非難したり、作業がその人のものではなかったと暗示したりしないでください。エージェントのカウントは下限値です。
編集済みのストーリーから --story <out>/story.json でリビルドします (タイミングは再計算されます)。
音楽: /brag がインストールされている場合、そのバンドルされているトラックとキュープリセットがそのまま使用できます (<brag-dir>/assets/music/*.mp3、<brag-dir>/assets/music/cues/*.music-cues.json)。動画と同じ長さ以上のトラックを推奨します。--cues を指定すると、シーンの開始が最も近いビートにスナップします。トラックがない場合、動画は無音になりますが、問題ありません。LinkedIn はミュート状態で自動再生します。
ステップ 3: チェック、レンダリング、確認
cd <out>/composition
npx hyperframes check # ゲート: エラーゼロ。line_unread と type-floor の警告も修正すること
npx hyperframes render --quality draft --output ../draft.mp4
ビートごとに 1 つの確定フレームを抽出し、最終レンダリング前にすべてを自分で確認してください。また、各チャプターカードのコマンド入力後 (カード開始から約 2.5 秒後) も確認してください。コマンド全体が 1 行で、暗い背景に明るいインクで画面に表示されている必要があります。
for t in $(jq -r '.beats[]|.start+.duration-0.5' ../story.json); do
ffmpeg -loglevel error -ss $t -i ../draft.mp4 -frames:v 1 ../frame-$t.png; done
確認項目: テキストのはみ出しやクリップ、year.json と一致しない数値、空または退屈なビート、スマートフォンサイズで読めないテキスト (フレームを 540px 幅にスケールして確認)、弱い最初のフレーム。原因を story.json (コピー) で修正するか、スキルのバグとして報告してください。その後:
npx hyperframes render --quality high --output ../year-in-review.mp4
ステップ 4: 納品
ポスター: フックの確定フレーム (約 2.9 秒) をサムネイルとして使用します。フレーム 0 として焼き付けることで、すべてのプラットフォームで表示されるようにします (/brag ステップ 4 と同じ手法):
cd <out>
ffmpeg -ss 2.9 -i year-in-review.mp4 -frames:v 1 -q:v 2 poster.jpg
ffmpeg -y -i year-in-review.mp4 -i poster.jpg \
-filter_complex "[0:v][1:v]overlay=0:0:enable='eq(n,0)'[v]" \
-map "[v]" -map '0:a?' -c:v libx264 -crf 20 -preset slow -pix_fmt yuv420p \
-c:a aac -b:a 160k -movflags +faststart tmp.mp4 && mv tmp.mp4 year-in-review.mp4
サムネイル: クローズ (年のグリッド、ハンドル、「, in review.」) を、スライドカウンター、ハッシュラベル、フッターレール、CTA なしのクリーンな静止画として保存します。これを LinkedIn の動画のカスタムサムネイルとしてアップロードします (動画と同じ 4:5 アスペクト比で、LinkedIn が期待する形式です)。カバー画像が必要な場所で使用してください:
cd <out>
npx hyperframes check thumbnail
npx hyperframes snapshot thumbnail --at 0.5 --no-end -o thumbnail/shots
cp thumbnail/shots/frame-00-at-0.5s.png thumbnail.png
ゲート: year-in-review.mp4 は H.264、1080x1350、50 MB 未満、25-75 秒 (ビルドは 70 秒 + チャプターカードで上限設定)。poster.jpg が存在すること。thumbnail.png は 1080x1350 で、目視確認済み (カウンター、レール、クリップがないこと)。
<out>/share-copy.txt を書き出します: 最も強力な事実 (アーキタイプ、1 つの数字、1 つのプロジェクト) から構築された、ユーザーの声で 2~3 文のプレーンな文章。ハッシュタグの壁は禁止、最大 2 つまで。例: "My 2026 on GitHub, so far: 30 new repos, a 44-day streak, and a bot that out-committed me. Made with github-year-in-review."
動画、サムネイル、ポスター、シェアコピーの場所と、動画が何を伝えているかを 1 行でユーザーに伝えてください。
クリエイティブのルール
- フレーム 0 が投稿そのもの。 名前、年、およびヘッドラインの数字を確定表示。
- 1 ビートにつき 1 つの質問、1 つの焦点。 大きな数字または 1 つの図形。それ以外はラベル。
- 目録ではなくアイデンティティ。 動画は合計ではなく、その人が誰だったか (アーキタイプ) で締めくくります。
- 正直に。 自動化は名前を出し、プライベート名は隠し、途中の年には "so far" と表示。
- ミュートでも読める。 すべてのビートは音がなくても意味が通じます。
- GitHub ではなく Git。 入力されたプロンプト、ハッシュラベル、差分ハンク、トレーラー。ロゴ、GitHub グリーン、UI クロムは禁止。
- オリジナルのルック。 references/story.md の元帳スタイル。Wrapped や Unwrapped にリスタイルしないでください。