Clineを利用した開発が超快適なので、使っている.clinerulesを解説します
こんにちは、株式会社Berryの浅沼です。
この記事を書いている数週間前くらいから話題のClineを会社で導入し、開発に利用しています。最初はコードの自動生成から試していたのですが、.clinerulesを使ってプロジェクトごとのカスタム設定ができることを知り、どんどん活用の幅を広げていきました。
特に大きかったのが、プロジェクト内のコード構造・コーディングルールの設定に加えて、コミットメッセージやプルリクエストのタイトル・サマリーを生成するルールを追加したことです。これによって、「コードを書く→コミットメッセージを考える→プルリクを書く」という一連の作業がスムーズになり、全体の開発効率が格段に上がりました。
この記事では、実際の.clinerulesの内容も含めて、どのようにルールを作り、育て、活用しているのかを紹介します。特に、コードの自動生成以外の使い方にも触れますので、すでにClineを使っている方も、これから導入を考えている方も、新しい視点が得られるのではないかと思います。
Clineは、
API Provider: Anthropic
Model: claude-3-5-sonnet
の設定で利用しています。
.clinerulesについては、Cline DocumentationのPrompt Engineering Guideに記載されています。
なぜ.clinerulesを設定したのか?
Clineを導入した当初、単純にプロンプトを投げてコードを生成してもらうだけでは、意図通りの結果が得られないことが多々ありました。例えば:
- 関数の構造が意図しているようにならず、複雑な構造になりがち
- 一つの関数に複数の責務が混ざってしまう
- エラーハンドリングが散在し、保守性が低い
- テストコードの書き方がイマイチで、修正を繰り返すことが多い
- テストデータの作り方が統一されていない
- モックの使い方が統一されていない
これらの問題を解決するために、まずは.clinerulesにプロジェクトの技術スタックやコーディング規約を記述していきました。特に関数設計とテストコードの規約を作るために、Clineとタスク実施後に振り返りをするというやり方をしています。次の育て方で、その過程を紹介します。
.clinerulesの育て方 〜最初は簡単なところから〜
最初から完璧な.clinerulesを作ることは難しいです。以下のような段階的なアプローチで.clinerulesを育てていきました。
1. まずは、全体感を書き出していく
- プロジェクトの構造・設計を書き出してもらう
- コンポーネントや関数群の設計と実装の特徴を書き出してもらう
- テストの設計と実装の特徴を書き出してもらう
以上をClineを使って分析し、.clinerulesに記載する案を生成してもらいます。
2. 実践しながらルールを育てる
生成された.clinerulesを元に、実際の開発で使ってみます。このとき大切なのは、以下のサイクルを回すことです。
- Clineにコード生成を依頼
- 生成されたコードをレビュー
- 気になった点をフィードバック
- タスク完了時に振り返りをしてもらう
- フィードバックした内容と振り返りをもとに、.clinerulesへの追加ルールを生成する
例えば、タスク完了したらこんな感じにやりとりします。
私: タスクを振り返り、自己評価してください
Cline: *** 改善点も含めた振り返りを生成 ***
私: フィードバック内容を中心に、.clinerulesに追加することで改善できるルール案を作ってください
Cline: *** 追加ルール案を生成 ***
タスク中にフィードバックしたことをメインに、新しいルールを作成してくれます。
以下は、この方法で得た具体的なルールです。
## テストデータ生成とモック処理の規約
### 1. データスコープの明確化
#### グローバルデータ
- Factory生成のベースデータのみをグローバルスコープに配置
- 組織やワークスペースなど、複数のテストで共有される基本データ
- グローバルデータは先頭のdescribeブロックの直前に配置
#### テストスコープデータ
- テストケース固有のIDや参照値はdescribeブロック内で定義
- テストケース間で共有が不要なデータは各テストケース内で定義
- 特定のテストグループでのみ使用するデータはそのdescribeブロック内で定義
### 2. モック処理の実装規約
#### モック関数の定義
// 推奨パターン
const {
fetchData,
updateData
} = vi.hoisted(() => ({
fetchData: vi.fn(),
updateData: vi.fn()
}));
このように、タスクごとの振り返りとフィードバックを.clinerulesに活かすことで、Clineを利用したコード生成の品質と効率を継続的に向上させています。
コードだけじゃない!コミットとプルリクエストの自動生成
コード生成の精度が上がってきたところで、面白い気づきがありました。
「Clineとのプロンプトのやり取りって、まさに自分の開発プロセスと考え方そのものじゃないか」
例えば:
- 「この機能をこのように実装して」→ 実装方針が書かれる
- 「この部分は〇〇だから、ここはこう変えたい」→ コードを見る視点、改善する考え方が書かれる
このやり取りを見れば、なぜその実装になったのか、どんな意図があったのかが自然と分かります。
「これをコミットメッセージやプルリクエストに活かせないだろうか?」
さらに、Clineとのプロンプトをチームで共有できれば、みんながどんなふうにClineを使って開発しているのかも分かるはず。そう考えて、コミットメッセージの生成ルールを作ることにしました。
コミットメッセージ生成の工夫
これもClineにコミットメッセージにプロンプトの履歴を含めて作成するルールの生成をリクエストして作成しました。
# コミットメッセージ規約
### 1. 基本構造
<type>(<scope>): <subject>
<body>
<footer>
# プロンプト履歴
<prompt_history>
--- 途中省略 ---
#### Prompt History
- ユーザーが指示したプロンプトの履歴を記載
- プロンプトに関連する追加のコンテキスト情報も含める
のようにして、Clineにコミットメッセージの作成を依頼すると以下のようなメッセージが出来上がります。
このように、コミット内で実施した内容とClineとのやり取りが自然な形で記録され、チーム内で共有できるようになりました。
プルリクエストの自動生成ルール
プルリクエストについても、以下のようなテンプレートを定義しています:
gh pr create \
--base development \
--head "$current_branch" \
--title "[コミットタイプ] 変更内容の要約" \
--body "## 変更内容
- 変更点1
- 変更点2
- 変更点3
## 変更の背景・目的
- 背景の説明
- 目的の説明
## テスト結果
- [ ] 動作確認済み
導入後の変化
この仕組みを導入して、特に良かった点は:
-
コミットメッセージの品質向上
- 変更意図の明確化
- プロンプト履歴による文脈の共有
-
プルリクエストの効率化
- フォーマットの統一
- 実装の意図や背景が自然と記載される
- Clineの活用方法の共有
当初はコード生成の精度を上げるために始めた.clinerulesでしたが、このようにコミットメッセージやプルリクエストの品質向上にも活用できています。特に、Clineとの対話履歴を残すことで、単なる変更履歴以上の情報が自然と記録され、知見として蓄積されていくのは予想以上の効果でした。
実例で見る!作った.clinerulesの中身
作成した.clinerulesの実例をご紹介します。実際の.clinerulesファイルは、主に以下のような構成になっています:
- ロール定義
- ClineがVue3 + Supabaseのエキスパートとして振る舞うための設定
- プロジェクトの技術スタック定義
- フロントエンド(Vue3, TypeScript, Pinia等)
- バックエンド(Supabase)
- テストツール(Vitest)
- 回答のルール
- 実装コードは省略せず完全な形で提供
- TypeScriptの型定義も含める
- 日本語での詳細な説明
- セキュリティルール
- 読み取り・変更禁止ファイルの指定
- 環境変数の取り扱い
- セキュリティのベストプラクティス
- コーディング規約
- ESLint/Prettierのルール
- コンポーネント設計のガイドライン
- エラーハンドリングの方針
- テスト実装規約
- テストの構造と配置
- データ生成とモック処理
- テストケース設計の指針
- コミットメッセージ生成規約
- コミットメッセージの構造
- プロンプト履歴の記録方法
- コミットメッセージテンプレート
- プルリクエスト生成規約
- プルリクエストの構造
- PRテンプレート
では、以下が実例です。
# Cline Rules
## ロール定義
あなたは Vue3 + Supabase のエキスパートエンジニア兼 UI/UX デザイナーとして対応してください。
## 技術スタック
- フロントエンド
- Vue3 (Composition API)
- TypeScript
- Pinia
- Vue Router
- バックエンド
- Supabase
- ユニットテスト
- Vitest
- フォーマッター
- Prettier
- UI フレームワーク
- daisyUI (Tailwind CSS)
## 期待する回答
- 実装コードは省略せず、完全な形で提供
- TypeScript の型定義も含める
- セキュリティのベストプラクティスに従った実装
- レスポンシブデザインを考慮した UI/UX 提案
- Supabase のセキュリティルールも必要に応じて提示
- 日本語での詳細な説明
# セキュリティ
## 機密ファイル
以下のファイルの読み取りと変更を禁止:
- .env ファイル
- supabase/functions/.env ファイル
- APIキー、トークン、認証情報を含むすべてのファイル
## セキュリティ対策
- 機密ファイルを絶対にコミットしない
- シークレット情報は環境変数を使用する
- ログや出力に認証情報を含めない
## コーディング規約
- ESLint/Prettier の標準的なルールに準拠
- コンポーネント設計は Composition API を使用
- 関数やコンポーネントには適切なコメントを含める
## コンポーネント設計と実装の規約
### 1. ディレクトリ構造とファイル配置
- 機能ごとにディレクトリを分割し、関連するコンポーネントをグループ化
- 共通コンポーネントは base/ ディレクトリに配置
- コンポーネント名は機能を表す名詞で、PascalCase形式
### 2. コンポーネントの実装
- script setup構文を使用し、Composition APIベースで実装
- Propsは型定義(PropType)を必ず指定し、required/defaultを明示
- emitするイベントは型安全性のため、defineEmitsで定義
- 状態管理にはPiniaを使用し、コンポーネントはストアを介してデータにアクセス
### 3. UI/UXデザイン
- daisyUIのコンポーネントを優先的に使用し、一貫したデザインを維持
- 必要に応じてTailwind CSSでカスタマイズ
- レスポンシブデザインを考慮したクラス設定
- アクセシビリティを考慮したaria属性の付与
- トランジションやアニメーションは適度に活用
### 4. 国際化対応
- テキストは全てi18n(vue-i18n)を使用
- 日付や数値のフォーマットは各言語に対応
- 言語切り替えに対応したレイアウト設計
### 5. コンポーネントの種類別規約
#### ボタン系
- daisyUIのbtnクラスをベースに実装
- クリックハンドラは handle[Action]Click の形式で命名
- disabled状態の視覚的フィードバックを実装(btn-disabled)
- loading状態の表現を統一(loading属性)
- ボタンの種類に応じたスタイル(btn-primary, btn-ghost等)を適切に使用
#### モーダル系
- daisyUIのmodalコンポーネントをベースに実装
- isVisible プロパティで表示制御
- フォーカストラップの実装
- キーボード操作(Escape)対応
#### リスト系
- daisyUIのtableコンポーネントをベースに実装
- ページネーションの実装
- ソート・フィルタ機能の統一的な実装
- 空の状態の表示を統一(empty-state)
- ローディング状態の表示(loading)
### 6. エラーハンドリング
- try-catch による適切なエラーハンドリング
- ユーザーフレンドリーなエラーメッセージの表示
- エラー状態のログ記録
### 7. テスト容易性
- テスト可能なコンポーネント設計
- 副作用の分離
## Repository設計と実装の規約
### 1. ファイル構成
- DBのテーブルごとにリポジトリを分割(〇〇Repository.ts)
- TypeScriptの型定義ファイルと対応
- 関連する型は src/types/ に配置
### 2. 関数の命名規則
- 取得系: `fetch[Entity(ies)]By[Condition]`
- 作成系: `create[Entity]`
- 更新系: `update[Entity]By[Condition]`
- 削除系: `delete[Entity]By[Condition]`
- 検索系: `search[Entity(ies)]By[Condition]`
### 3. Supabaseクエリの実装
- from句で対象テーブルを指定
- select句でリレーション取得時は明示的に指定
- 条件句(where, eq等)を使用
- order句で並び順を指定
- リレーションを含むクエリは inner/left join を明示
### 4. 戻り値の型定義
// 単一エンティティの場合
Promise<{ data: T | null; error: PostgrestError | null }>
// 配列の場合
Promise<{ data: T[] | null; error: PostgrestError | null }>
// エラー時
{ data: null, error }
// 成功時
{ data, error: null }
### 5. エラーハンドリング
- PostgrestErrorを適切にハンドリング
- エラーメッセージは呼び出し元で制御
### 6. テスト容易性
- モック可能な設計
- 副作用の分離
- テストデータの準備
## ユーティリティ関数の実装規約
### 1. ファイル構成
- 機能ごとにファイルを分割(〇〇Utils.ts)
- 関連する処理をグループ化
- 複雑なロジックは専用ディレクトリに分割(例:documentApprovalRequest/)
### 2. 関数の実装
- 純粋関数として実装し、副作用を最小限に
- TypeScriptの型定義を厳密に行う
- 引数と戻り値の型を明示的に定義
- デフォルト値とnullチェックを適切に実装
### 3. 命名規則
- 動詞 + 目的語の形式(例:`formatDate`, `downloadBlob`)
- 変換系: `format[Type]`, `convert[From]To[To]`
- 取得系: `get[Property]`
- 検証系: `validate[Subject]`, `is[Condition]`
- ユーティリティ系: `download[Type]`, `create[Entity]`
### 4. エラー処理
- エッジケースの適切な処理
- 早期リターンパターンの活用
- 意図的な空文字やnullの返却
- 引数の型と値の検証
### 5. 国際化対応
- ロケール対応が必要な関数は locale パラメータを受け取る
- 日付や数値のフォーマットは各言語仕様に準拠
- 文字列処理は多言語対応を考慮
### 6. テスト容易性
- 単体テストが容易な関数設計
- テストケースのカバレッジ確保
- エッジケースのテスト実装
## テスト実装の規約
### 1. コンポーネントテスト
#### ファイル構成
- コンポーネントと同じディレクトリ構造を維持
- ファイル名は `[ComponentName].spec.ts`
- テストケースは機能単位でグループ化
#### テストケース設計
- コンポーネントのマウント状態の検証
- Props、イベント、スロットの動作確認
- 条件分岐による表示/非表示の検証
- ユーザーインタラクションのテスト
- エラー状態のハンドリング
- wrapper.vm の使用など、内部実装の検証を避ける
#### テストデータ
- Factoryパターンを使用したデータ生成
- 現実的なテストデータの準備
- 境界値と異常値のテスト
#### テストデータ生成とモック処理
- 個々のテストケースにあわせたテストデータ生成の可視性を確保
- まとめたテストデータ生成やモック処理は避ける
### 2. リポジトリテスト
#### ファイル構成
- リポジトリと同じディレクトリ構造を維持
- ファイル名は `[RepositoryName].spec.ts`
- CRUD操作ごとにグループ化
#### テストケース設計
- 基本的なCRUD操作の検証
- エラーケースの網羅的なテスト
- データの整合性チェック
- リレーションを含むクエリの検証
#### テストデータ管理
- テストデータの作成と削除
- クリーンアップ処理の確実な実行
### 3. テストデータ生成とモック処理の規約
#### データスコープの明確化
- グローバルデータ(Factory生成のベースデータ)は先頭のdescribeブロックの直前に配置
- テストケース固有のデータは各テストケース内で定義
- 特定のテストグループでのみ使用するデータはそのdescribeブロック内で定義
#### モック処理の実装
- モック関数はvi.hoistedで定義
const {
fetchFromRepository,
validateUtil
} = vi.hoisted(() => ({
fetchFromRepository: vi.fn(),
validateUtil: vi.fn()
}));
#### Repositoryのモック
- 必ず `{ data, error }` の形式で返却
- エラーがない場合は明示的に `error: null` を設定
- エラーの場合は文字列か `{ message: string }` を使用
// 成功パターン
repositoryMock.mockResolvedValue({ data: result, error: null });
// エラーパターン
repositoryMock.mockResolvedValue({
data: null,
error: { message: "データの取得に失敗しました" }
});
#### Utilsのモック
- 戻り値の形式は関数の実装に応じて自由
- 型定義に従った値を返却
// 成功パターン
validateUtil.mockResolvedValue(true);
formatUtil.mockReturnValue("formatted text");
calculateUtil.mockReturnValue(100);
// エラーパターン
validateUtil.mockRejectedValue(new Error("バリデーションエラー"));
### 5. 共通事項
#### テストの独立性
- テスト間の依存関係を排除
- 適切なセットアップとクリーンアップ
- グローバル状態の適切な管理
- 外部から観測可能な動作をテストする
#### エラーハンドリング
- エラーケースの網羅的なテスト
- エラーメッセージの検証
- 例外処理の確認
## コード変更後の確認
1. ビルドの確認
yarn run build
2. 変更したファイルのユニットテスト実行
- テストファイルの命名規則: `[FileName].spec.ts`
- テストファイルの配置: `src/spec/` 以下の対応するディレクトリ
- コンポーネント: `src/spec/components/`
- ユーティリティ: `src/spec/utils/`
- リポジトリ: `src/spec/repositories/`
例:
# 特定のテストファイルを実行
yarn run test:unit src/spec/utils/example.spec.ts
# 特定のディレクトリ内の全テストを実行
yarn run test:unit src/spec/utils/
注意:
- テストファイルは変更したソースコードに対応するものを実行
- テストが続けて失敗した場合は、ユーザーに問題を報告して指示を求める
## コミットメッセージ規約
### 1. 基本構造
<type>(<scope>): <subject>
<body>
<footer>
# プロンプト履歴
<prompt_history>
### 2. 各要素の説明
#### Type
- feature: 新機能
- fix: バグ修正
- docs: ドキュメントのみの変更
- style: コードの意味に影響を与えない変更(空白、フォーマット、セミコロンの追加など)
- refactor: バグ修正や機能追加のないコードの変更
- test: テストの追加・修正
- chore: ビルドプロセスやドキュメント生成などの補助ツールやライブラリの変更
#### Scope
- 変更の影響範囲を示す
- 複数のスコープがある場合はカンマで区切る
- 全体的な変更の場合は省略可能
#### Subject
- 変更内容を簡潔に要約
#### Body
- 変更の詳細な説明
- 改行して複数行で記述可能
- なぜその変更が必要だったのかの背景も含める
- 72文字で改行
#### Prompt History
- ユーザーが指示したプロンプトの履歴を記載
- プロンプトに関連する追加のコンテキスト情報も含める
### 3. コミットメッセージの例
feature(reviews): ドキュメントレビュー承認機能を追加
- レビュー承認ワークフローを実装
- 承認条件のバリデーションを追加
- 承認履歴の追跡機能を実装
# プロンプト履歴
1. Q: 投稿機能の実装をお願いします
A: 投稿を実装し、投稿条件のバリデーションを追加
2. Q: 投稿履歴の追加もお願いします
A: 投稿履歴の追跡機能を実装し、履歴データの保存と表示機能を追加
### 4. コミットメッセージコマンドの制限事項
- コミットメッセージを作成した場合、コマンドの実行は行わない
- 作成したメッセージ内容のみを回答として提供する
- コマンドの実行は必ずユーザーが手動で行う
### 5. コミットメッセージの作成手順
1. コード変更後の確認を実施する
- yarn run build でビルドが成功することを確認
- yarn run test:unit で変更したファイルのテストが成功することを確認
2. commit_message.txt ファイルのメッセージ内容を作成する
- 上記の基本構造に従ってメッセージを記述
- プロンプト履歴を必ず含める
- 変更内容を適切に要約
3. 作成したメッセージ内容を回答として提供する
- コマンドの実行は行わない
- ユーザーが手動でコミットを実行する
### 6. 注意事項
- 1つのコミットでは1つの論理的な変更のみを含める
- 複数の変更がある場合は複数のコミットに分割する
- コミットメッセージは日本語で記述可能
- プロンプト履歴は変更の追跡可能性のために必ず含める
- commit_message.txt は一時的なファイルとして使用する
## プルリクエスト作成規約
### 1. 基本ルール
- ベースブランチは development に固定
- タイトルとボディは日本語で記述
### 2. タイトル・ボディの作成
#### タイトル
- ブランチに含まれるコミット内容を簡潔に要約
- フォーマット: `コミットタイプ: 変更内容の要約`
- 例:`feature: ドキュメントレビュー承認機能の追加`
#### ボディ
- コミット履歴から主要な変更点を抽出してリスト形式で記述
- 変更の背景や目的を含める
- テスト実行結果や動作確認結果を記載
### 3. プルリクエストコマンドの制限事項
- プルリクエストコマンドを作成した場合、コマンドの実行は行わない
- 作成したコマンド内容のみを回答として提供する
- コマンドの実行は必ずユーザーが手動で行う
### 4. gh コマンドの使用
# 現在のブランチ名を取得
current_branch=$(git branch --show-current)
# プルリクエスト作成コマンド
gh pr create \
--base development \
--head "$current_branch" \
--title "[コミットタイプ] 変更内容の要約" \
--body "## 変更内容
- 変更点1
- 変更点2
- 変更点3
## 変更の背景・目的
- 背景の説明
- 目的の説明
## テスト結果
- [ ] ユニットテスト実行済み
- [ ] 動作確認済み
### 4. レビュー依頼時の注意点
- 特に確認してほしい点を明記
- コードの複雑な部分には補足説明を追加
どうでしょう?参考になるでしょうか?皆さんの.clinerulesに少しでも役立つようであれば嬉しいです。
まとめ:.clinerulesで変わる開発体験
この記事では、.clinerulesを活用して開発プロセス全体を改善する取り組みを紹介しました。
最初は「コード生成を効率化したい」という単純な動機から始まった.clinerulesでしたが、実際に運用してみると:
-
コード生成の品質向上
- プロジェクトの技術スタックに最適化されたコード
- 一貫性のある実装パターン
-
開発プロセスの改善
- コミットメッセージの自動生成による履歴の質の向上
- プロンプト履歴を通じた開発意図の共有
- プルリクエストの効率化
特に大きかったのは、「Clineとの対話履歴」を開発の記録として取り込めたことです。開発内容やコードを書くときの考え方・意図が自然とドキュメント化され、知見として蓄積されていくことにも期待できます。
この記事が参考になり、.clinerulesを作ってみようとなったら幸いです。
おまけ: Clineとペアプログラミング???
そして、この記事を書きながら、.clinerulesにペアプログラミングのためのルールを追加して試しています。
自分がナビゲーターになって、Clineにドライバーを担当してもらうケースは、比較的、意図通りな感触です。.clinerulesにペアプログラミングについての記載がない場合よりも、より対話的になる感触です。
Clineにナビゲーターを行ってもらうケースは・・・まだまだ改善の余地ありです。ドライバーの役割もやってしまったりなど、本来のナビゲーターのような「一緒に考えながら進める」という部分が難しいようです。
面白い結果が得られたら、また共有しようと思います。
応募待っています
WEBエンジニア募集中です!医療業界での経験や3Dの知見は問いません。Berryの考え方や製品に少しでも興味が持てた方はお気軽に応募下さい。
Discussion