[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
株式会社Berry
😺

Clineを利用した開発が超快適なので、使っている.clinerulesを解説します

2025/01/27に公開

こんにちは、株式会社Berryの浅沼です。
この記事を書いている数週間前くらいから話題のClineを会社で導入し、開発に利用しています。最初はコードの自動生成から試していたのですが、.clinerulesを使ってプロジェクトごとのカスタム設定ができることを知り、どんどん活用の幅を広げていきました。

特に大きかったのが、プロジェクト内のコード構造・コーディングルールの設定に加えて、コミットメッセージやプルリクエストのタイトル・サマリーを生成するルールを追加したことです。これによって、「コードを書く→コミットメッセージを考える→プルリクを書く」という一連の作業がスムーズになり、全体の開発効率が格段に上がりました。

この記事では、実際の.clinerulesの内容も含めて、どのようにルールを作り、育て、活用しているのかを紹介します。特に、コードの自動生成以外の使い方にも触れますので、すでにClineを使っている方も、これから導入を考えている方も、新しい視点が得られるのではないかと思います。

Clineは、

API Provider: Anthropic
Model: claude-3-5-sonnet

の設定で利用しています。

.clinerulesについては、Cline DocumentationのPrompt Engineering Guideに記載されています。
https://docs.cline.bot/improving-your-prompting-skills/prompting

なぜ.clinerulesを設定したのか?

Clineを導入した当初、単純にプロンプトを投げてコードを生成してもらうだけでは、意図通りの結果が得られないことが多々ありました。例えば:

  • 関数の構造が意図しているようにならず、複雑な構造になりがち
    • 一つの関数に複数の責務が混ざってしまう
    • エラーハンドリングが散在し、保守性が低い
  • テストコードの書き方がイマイチで、修正を繰り返すことが多い
    • テストデータの作り方が統一されていない
    • モックの使い方が統一されていない

これらの問題を解決するために、まずは.clinerulesにプロジェクトの技術スタックやコーディング規約を記述していきました。特に関数設計とテストコードの規約を作るために、Clineとタスク実施後に振り返りをするというやり方をしています。次の育て方で、その過程を紹介します。

.clinerulesの育て方 〜最初は簡単なところから〜

最初から完璧な.clinerulesを作ることは難しいです。以下のような段階的なアプローチで.clinerulesを育てていきました。

1. まずは、全体感を書き出していく

  1. プロジェクトの構造・設計を書き出してもらう
  2. コンポーネントや関数群の設計と実装の特徴を書き出してもらう
  3. テストの設計と実装の特徴を書き出してもらう

以上をClineを使って分析し、.clinerulesに記載する案を生成してもらいます。

2. 実践しながらルールを育てる

生成された.clinerulesを元に、実際の開発で使ってみます。このとき大切なのは、以下のサイクルを回すことです。

  1. Clineにコード生成を依頼
  2. 生成されたコードをレビュー
  3. 気になった点をフィードバック
  4. タスク完了時に振り返りをしてもらう
  5. フィードバックした内容と振り返りをもとに、.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

## 変更の背景・目的
- 背景の説明
- 目的の説明

## テスト結果
- [ ] 動作確認済み

導入後の変化

この仕組みを導入して、特に良かった点は:

  1. コミットメッセージの品質向上

    • 変更意図の明確化
    • プロンプト履歴による文脈の共有
  2. プルリクエストの効率化

    • フォーマットの統一
    • 実装の意図や背景が自然と記載される
    • Clineの活用方法の共有

当初はコード生成の精度を上げるために始めた.clinerulesでしたが、このようにコミットメッセージやプルリクエストの品質向上にも活用できています。特に、Clineとの対話履歴を残すことで、単なる変更履歴以上の情報が自然と記録され、知見として蓄積されていくのは予想以上の効果でした。

実例で見る!作った.clinerulesの中身

作成した.clinerulesの実例をご紹介します。実際の.clinerulesファイルは、主に以下のような構成になっています:

  1. ロール定義
  • ClineがVue3 + Supabaseのエキスパートとして振る舞うための設定
  1. プロジェクトの技術スタック定義
  • フロントエンド(Vue3, TypeScript, Pinia等)
  • バックエンド(Supabase)
  • テストツール(Vitest)
  1. 回答のルール
  • 実装コードは省略せず完全な形で提供
  • TypeScriptの型定義も含める
  • 日本語での詳細な説明
  1. セキュリティルール
  • 読み取り・変更禁止ファイルの指定
  • 環境変数の取り扱い
  • セキュリティのベストプラクティス
  1. コーディング規約
  • ESLint/Prettierのルール
  • コンポーネント設計のガイドライン
  • エラーハンドリングの方針
  1. テスト実装規約
  • テストの構造と配置
  • データ生成とモック処理
  • テストケース設計の指針
  1. コミットメッセージ生成規約
  • コミットメッセージの構造
  • プロンプト履歴の記録方法
  • コミットメッセージテンプレート
  1. プルリクエスト生成規約
  • プルリクエストの構造
  • 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の考え方や製品に少しでも興味が持てた方はお気軽に応募下さい。
https://www.wantedly.com/projects/1950414

株式会社Berry
株式会社Berry

Discussion