はじめに
みなさん、Claude Code の /loop はもう試してみましたか?
/loop は「指定したプロンプトやスラッシュコマンドを、一定間隔で繰り返し実行してくれる」機能です。デプロイの完了監視や PR のステータスチェックのような繰り返し作業を Claude にまかせられるもので、Claude Code v2.1.72 以降で利用できます。詳しい仕様は公式ドキュメントにまとまっています。
なお、cron のようにバックグラウンドで常駐するものではなく、Claude Code のセッションを開いている間だけ動く点には注意してください(定期タスクは作成から7日で自動的に期限切れになります)。
便利そうなのはわかる。でも、いざ使おうとするとこうなりませんか?
「で、何をループさせればいいの……?」
私も最初はそうでした。この記事では、私が実際に回してみて「これは/loopの正解パターンのひとつだ」と感じた使い方 —— 勉強用のサンプルコードを自動で増やし続ける —— を、実際のリポジトリと設定ファイルを全部見せながら紹介します。
こんな人に向けて書いています。
- Claude Code で loop 作業をやってみたいが、何をさせればいいのかわかっていない人
- 勉強するにあたって、参考になるコード(写経・読解の素材)を増やしたいと思っている人
何ができたのか(結果から)
Nuxt 4 + Three.js で作った GLSL シェーダーのギャラリーサイトに、/loop を仕掛けました。
/loop 20m /add-shader
たったこれだけです。「20分ごとに /add-shader というカスタムスラッシュコマンドを実行する」という意味です。
結果がこちら。
- 1週間で89個のシェーダーコンポーネントが自動追加された(ギャラリー全体では200個超)
- 1コミット = 1シェーダーで、実装 → ギャラリー登録 → Storybook ストーリー作成 → lint/フォーマット → 動作確認 → commit までが全自動
- git log がそのまま「GLSL表現の作例集の目次」になっている
$ git log --oneline | head
12c5f7c feat: Geyser(間欠泉)シェーダーコンポーネントを追加
be4b59f feat: Halo(暈)シェーダーコンポーネントを追加
f0a4d46 feat: Koyo(紅葉)シェーダーコンポーネントを追加
7758162 feat: Anemone(イソギンチャク)シェーダーコンポーネントを追加
7336522 feat: Snowflake(雪の結晶)シェーダーコンポーネントを追加
8d55905 feat: Moonrise(月の出)シェーダーコンポーネントを追加
850a349 feat: Chrysanthemum(菊)シェーダーコンポーネントを追加
間欠泉、暈(ハロ)、紅葉、イソギンチャク、雪の結晶……。テーマ選定も Claude まかせですが、「既存と被らないテーマを選べ」という指示だけで、自然現象・鉱物・生物・宇宙とバリエーション豊かに増えていきます。正直、朝起きてコミットログを眺めるのがちょっと楽しみになります。
なぜ「勉強素材の自動生成」が /loop の正解パターンなのか
/loop に向いているタスクの条件を、回してみて実感した順に挙げます。
1. 1回分の作業が独立して完結する
「シェーダーを1個追加する」は、前回の結果に依存しません。1回失敗しても次のループに影響しない。これが連鎖するタスク(リファクタリングの続きなど)だと、1回の失敗が雪だるま式に壊れていきます。
2. 何回繰り返しても価値が積み上がる
サンプルコードは多ければ多いほど、勉強素材として価値が上がります。「同じパターンで書かれた GLSL の実装が89個ある」というのは、1個の完璧なチュートリアルとは別種の価値があります。fbm ノイズの使い方だけでも、炎・雲・岩・水面と何通りもの「使われ方」を比較して読めるからです。
3. 成功/失敗が機械的に判定できる
lint が通る、ページが200を返す、シェーダーのコンパイルエラーが出ない。人間の主観レビューなしでも「壊れていないこと」は保証できます。
逆に言うと、この3条件を満たすタスクを見つけられれば、シェーダーに限らず何でも /loop の素材になります(記事の最後にアイデア集を載せます)。
仕込みは「CLAUDE.md + カスタムスラッシュコマンド」の2つだけ
/loop 20m /add-shader の1行を支えているのは、次の2つのファイルです。
three-nuxt/
├── CLAUDE.md # リポジトリの規約(毎回読まれる前提知識)
└── .claude/
└── commands/
└── add-shader.md # /add-shader の指示文(ループ1回分の作業定義)
CLAUDE.md:守ってほしい「型」を書く
CLAUDE.md には、全コンポーネント共通の実装パターンを書いています。抜粋するとこんな感じです。
### Gallery コンポーネントの規約
`app/components/Gallery/{Name}/index.vue` の形式で配置する。
各コンポーネントの実装パターン(全コンポーネント共通):
1. `withDefaults(defineProps<{ width?: number; height?: number }>(), ...)` で任意の props を定義
2. `useTemplateRef<HTMLDivElement>("container")` でマウント先を取得
3. `onMounted` で `WebGLRenderer({ antialias: true })` を初期化
4. シーンは `OrthographicCamera(-1, 1, 1, -1)` + `PlaneGeometry(2, 2)` のフルスクリーンクアッドが基本形
5. GLSL は文字列テンプレートリテラルとして書き、`THREE.ShaderMaterial` に渡す
6. `THREE.Clock` の経過時間を `uTime` uniform に渡してアニメーション
7. `onUnmounted` で `cancelAnimationFrame` と `renderer.dispose()`・`material.dispose()` を呼ぶ
ここが勉強素材化のキモです。型を固定しているおかげで、89個のコンポーネントは「差分がフラグメントシェーダーだけ」になります。つまり読むときは GLSL の部分だけに集中すればいい。写経するときも、ボイラープレートは1回覚えれば全部に通用します。
add-shader.md:ループ1回分の作業を「commit まで」定義する
.claude/commands/add-shader.md が、ループ1周でやることの全定義です。構成はこうなっています。
# 新しい GLSL シェーダーコンポーネントを 1 つ追加する
## 1. テーマ選定
- 既存エントリを確認し、**まだ扱われていないテーマ**を 1 つ選ぶ
- 既存シェーダーと視覚的に類似しすぎるテーマは避ける
## 2. コンポーネント実装
- CLAUDE.md「Gallery コンポーネントの規約」に従う
- フラグメントシェーダーには日本語コメントでセクション見出しを付ける
## 3. ギャラリー登録
- `app/data/gallery.ts` の `galleryItems` に追加する
## 4. Storybook ストーリー
- CLAUDE.md のテンプレート通りに作成する
## 5. 検証
- `npm run lint` がエラー 0 であること
- 追加・変更したファイルに `npx oxfmt` をかける
- `/gallery/{name}` が 200 を返すこと・コンパイルエラーが出ていないこと
## 6. コミット
feat: {Name}({日本語名})シェーダーコンポーネントを追加
ポイントは 「commit までがワンセット」 と明記していることです。これがないと、ループが回るたびに未コミットの変更が積み重なって、どこかの周回で衝突して崩壊します。1周 = 1コミットで完結させると、各周回が独立し、失敗した周回だけ捨てられるようになります。
運用して学んだこと(ハマりどころ)
ここが一番お伝えしたいところです。/loop は「回し始めてから指示文を育てる」ものでした。
1. バグは「直す」より先に「指示文に書く」
このリポジトリには「コンポーネント名に大文字が2箇所あると詳細ページが404になる」という既知のバグがありました。ループ中に修正する時間はないので、まず add-shader.md にこう書きました。
コンポーネント名は大文字を 1 箇所だけ含む 1 語にする(例:
Icefloe○ /IceFloe×)
バグ修正よりも先に「地雷の位置を教える」。自動化ではこの順番のほうが即効性があります。
2. 暗黙の前提は必ず踏み抜かれる
途中で詳細ページに lil-gui のパラメータ調整パネル(速度・一時停止・色調整)を追加したのですが、これは「全コンポーネントが THREE.Clock で時間管理している」ことを前提にした汎用設計でした。
すると案の定、ある周回で performance.now() を使った独自時間管理のシェーダーが生まれかけました。人間のチーム開発と同じで、書いていない規約は存在しない規約です。以下を指示文に追記して解決しました。
時間管理は
THREE.ClockのgetElapsedTime()のみを使う。performance.now()やuTime += 0.01などの独自時間管理を使うと速度調整が効かなくなる
3. 「テーマが被らない」もルール化できる
89回も回すと、放っておけば「波」「オーロラ」ばかりになります。「既存エントリを確認してからテーマを選ぶ」「視覚的に類似しすぎるテーマは避ける」の2行で、テーマの多様性は保たれました。タグの語彙も既存13種から選ばせることで、「1件しか使われないタグ」の乱造も防げています。
4. 検証ステップをケチらない
1周20分のうち、実装は半分くらいで、残りは lint・フォーマット・dev サーバーでの動作確認に使われています。もったいなく感じますが、無人で回すループでは「壊れたものを積まない」ことが最優先です。検証を薄くして周回速度を上げるより、1周を確実に完結させるほうが最終的な成果物は多くなります。
できあがったリポジトリを「教材」として使う
自動生成されたリポジトリは、そのまま勉強素材になります。私の使い方はこの3つです。
1. git log を目次にして差分を読む
1コミット = 1シェーダーなので、git show するだけで「このテーマはこう実装した」が差分として読めます。
git log --oneline | grep 雪
git show 7336522 # Snowflake の実装全体が1コミットで見える
2. Storybook でカタログとして眺める
全コンポーネントにストーリーが付いているので、npm run storybook で200個超のシェーダーを一覧で見比べられます。「この表現いいな」→ 該当ファイルの GLSL を読む、という流れが最短です。
3. GLSL のイディオムを横断検索する
型が揃っているので grep が効きます。たとえば fbm(フラクタルノイズ)を使っている実装を全部並べて、パラメータの違いが見た目にどう効くかを比較できます。
grep -rl "float fbm" app/components/Gallery | head
生成されたコードには日本語コメントでセクション見出しが付いているのも地味に効いています(これも指示文で強制した項目です)。たとえば間欠泉シェーダーには、イエローストーンの熱泉の温度と微生物マットの色の対応がコメントで書かれていて、「へえ」となりながら読めます。
あなたのリポジトリで /loop させるネタ集
「独立して完結する・積み上がる・機械的に検証できる」を満たすタスクの例です。
| ネタ | ループ1回分の作業 |
|---|---|
| CSSアニメーション作例集 | 未実装のイージング/エフェクトを1つ実装 + デモページ登録 |
| アルゴリズム実装集 | 未実装のアルゴリズムを1つ、テスト付きで実装 |
| UIコンポーネントカタログ | ボタン/カード等のバリエーションを1つ + Storybook |
| 正規表現・SQLの練習問題集 | 問題と解答・解説を1問追加(テストで解答を検証) |
| デザインパターン写経集 | 1パターンを自分の言語で実装 + 使い所のREADME |
| 競プロ典型問題の解法集 | 典型問題1問の解法 + 計算量の解説コメント |
共通する設計は全部同じです。
- CLAUDE.md に「1件あたりの型」を固定して書く
- カスタムスラッシュコマンドに「選定 → 実装 → 登録 → 検証 → commit」のワンセットを書く
-
/loop 20m /コマンド名で放流する - 変な成果物が出たら、直すより先に指示文に禁止事項を書き足す
まとめ
-
/loopの入門には「勉強素材を自動で増やす」タスクが向いている。1回分が独立していて、積み上がって、機械的に検証できるから - 仕込みは CLAUDE.md(型の定義)とカスタムスラッシュコマンド(1周分の作業定義)の2ファイルだけ
- 「commit までワンセット」「バグより先に指示文」「暗黙の前提は書く」が運用のコツ
- できあがったリポジトリは、git log が目次・Storybook がカタログ・grep が横断検索になる教材
「何をループさせればいいかわからない」だった1週間前の自分に見せたい結果になりました。ぜひ小さな作例集リポジトリを1つ作って、/loop 20m で一晩放流してみてください!朝のコミットログには、きっとちょっと感動するはずです。
参考リンク