VibeCoder は、「AI とペアプロしている画面」を映像として流すジェネレーターです。4 ペインのエディタに、色分けされたコード、アテンションのヒートマップ、学習曲線が並んで動きます。配信の背景や動画素材として使うためのものです。
#🎯 中身が無い、を正面から作る
このサービスは何も計算しません。AI も動いていないし、コードも実行されません。「そう見える画面」だけを作っています。
一見ふざけた題材ですが、作るものははっきりしていました。
- 配信の背景に流す
- 作業用の BGM 的な視界
- 動画のカット素材
つまり 見ていて飽きない画面が要件のすべてです。実用性ではなく、時間あたりの情報量と間の取り方で評価が決まります。
#📜 全部を「台本」として持つ
最初にランダム生成を試しましたが、すぐ破綻しました。ランダムだと話の流れがなく、コードが増えたり減ったりして、見ていて意味が取れません。
そこでシーンを台本として持つ構造にしました。
{ type: "thought", chunk: { kind: "tool", text: "→ accelerate launch --num_processes 4 train/trainer.py" } },
{ type: "metric", metric: { tokensPerSec: 1280, gpu: 92, vram: 18.4, loss: 2.84 } },
{ type: "thought", chunk: { kind: "ok", text: " step 100/3000 · loss 2.84 · lr 2.0e-4" } },
{ type: "delay", ms: 500 },
{ type: "metric", metric: { tokensPerSec: 1310, gpu: 94, loss: 2.41 } },ステップの種類は数種類だけです。
| type | 意味 |
|---|---|
thought | 左ペインに 1 行流す |
metric | 指標パネルを更新 |
delay | 間を置く |
tree | ファイルツリーに印を付ける |
notify | 通知を出す |
すべて純粋なデータで、動きのロジックは再生側にあります。 台本を書くだけで新しいシーンが増える構造にしたので、5 シーンぶん書くのが苦になりませんでした。
#⏱️ 間(ま)が全部だった
一番調整したのが delay です。等間隔で流すと、機械的で見ていられません。
- コマンドを打ってから結果が出るまでは少し待つ
- ログが連続で流れるところは速く
- 学習が進むところは500ms 刻みで淡々と
- 完了通知の前はやや長く溜める
この緩急が「作業している感じ」を作ります。実装は setTimeout を挟むだけですが、値の置き方で印象がまったく変わりました。
損失が 2.84 → 2.41 → 1.94 → 1.42 → 1.08 と下がっていくのも、下がり幅を後半ほど小さくしています。実際の学習曲線がそうなるからで、等間隔に下げると嘘に見えます。
#🎨 コードの色分けを自前で書く
エディタペインには色分けされたコードが流れます。ハイライタは依存を足さず自前で書きました。
export function tokenize(code: string, lang: Lang): Array<[string, TokenKind]>対応言語は tsx / py / rust / go / sql / yaml の 6 つ。完全なパーサではなく、
- 空白と改行
- コメント(
#か//) - 文字列
- 数値
- キーワード(言語ごとの一覧)
- それ以外
に分けるだけの近似です。映像として流れるだけなので、多少の誤判定は問題になりません。 正確さより、依存ゼロと軽さを取りました。
#🔥 アテンションのヒートマップ
8×8 のマス目に色の濃淡を出します。中身は乱数ですが、それらしく見えるための細工が入っています。
export function randomAttention(seed: number): number[][]一様乱数だと、ただのノイズにしか見えません。対角線付近を強めにして、行ごとに重みの偏りを作ると、アテンション行列らしい構造が出ます。シード付きなので、シーンを再生し直しても同じ模様になります。
#😓 苦労したところ
本物と誤解されないようにする。 実際に AI が動いていると思われると困ります。画面の説明と FAQ で「これは演出であり、モデルは動いていない」と明示しました。見た目を作るサービスほど、何であるかを言葉で書く必要があります。
5 テーマの配色。 配信背景として使うので、上に人物やワイプが乗ることを前提にしました。中央が明るすぎると文字が読めなくなるので、明度の分布を周辺に寄せています。
永久に流し続ける。 シーンが終わったら次のシーンへ、最後まで行ったら最初へ戻ります。ループしていることに気づかれない程度の長さ(1 シーン 10〜18 ステップ × 5 シーン)にしました。
リソースを食わない。 背景として何時間も流されるので、requestAnimationFrame で重い描画を続けるわけにはいきません。更新はステップ単位のイベント駆動にして、何も起きていない間は何も描かない構成にしています。
#🔭 今後の拡張
- 台本のカスタマイズ(自分のプロジェクト名を入れる)
- 解像度の指定(配信レイアウトに合わせる)
- 動画としての書き出し
- シーンの追加(デプロイ、障害対応、レビュー)
#💡 このサービスから言えること
演出だけのものを作るときも、データと再生ロジックを分けると作りやすくなります。 台本を配列として書けるようにしたから、シーンを増やすのが単なる執筆作業になりました。動きのコードに直接書き込んでいたら、2 シーン目で嫌になっていたはずです。
そして**「間」はコードに書ける**ということ。500ms をどこに置くかで、同じ内容が退屈にも自然にも見えます。数字を並べるだけの調整ですが、ここがこのサービスの本体でした。
[ ./next_action ]
読んだら、 VibeCoder を実際に動かす。
この開発ログは VibeCoder をどう作ったかの記録です。 読み終わったらそのままサービス本体へ戻って、 実物で価値を確かめてください。