claude.aiとclineを活用したコストと精度を両立するAI駆動開発手法

## はじめに

ソフトウェア開発において、コストを抑えつつ高精度な成果物を得ることは重要な課題です。本記事では、**ChatGPT**や**claude.ai**といったWeb UIベースのAIと、**cline（旧Claude-dev）**を組み合わせて効率的に開発を進める方法をご紹介します。具体的なコード例や手順を交えながら、2つのステップで解説します。

<blockquote class="twitter-tweet" data-media-max-width="800"><p lang="ja" dir="ltr">cline (旧：Claude-dev) をコスト的にも精度的にもいい感じに使うには<br>1⃣WEB UIベースで要件を固める<br>→まず定額なのでコスパがいい<br>→結構構成で紆余曲折するときが多い＊これをcline上でやると結構フォルダ構成がファイルが大変なことになる。。。<br>→フォルダ構成やコアなコードを生成させる… <a href="https://t.co/SHyZgocmv2">pic.twitter.com/SHyZgocmv2</a></p>&mdash; Maki@Sunwood AI Labs. (@hAru_mAki_ch) <a href="https://twitter.com/hAru_mAki_ch/status/1847290392758346206?ref_src=twsrc%5Etfw">October 18, 2024</a></blockquote> 

## cline（旧Claude-dev）とは？

**cline**は、CLIとエディタを自在に操ることができるAIアシスタントです。高度なエージェント機能を持つ[Claude 3.5 Sonnet](https://www-cdn.anthropic.com/fed9cc193a14b84131812372d8d5857f8f304c52/Model_Card_Claude_3_Addendum.pdf)を基盤に、複雑なソフトウェア開発タスクをステップバイステップで処理します。ファイルの作成・編集、コマンドの実行、プロジェクトの分析など、多彩な機能を持ち、開発者の生産性を大幅に向上させます。

## ステップ1：Web UIベースで要件を固める

最初のステップでは、**ChatGPT**や**claude.ai**などのWeb UIベースのAIを使用して、プロジェクトの要件を明確にします。


### 定額制でコスパが良い

- **無制限の試行錯誤**：Web UIは定額制のプランが多く、コストを気にせずに何度でもアイデアの検証が可能です。


### 構成の試行錯誤が容易

- **複雑化を防ぐ**：プロジェクトの構成を練る際、Web UI上で紆余曲折することが多いですが、cline上でこれを行うとフォルダ構成やファイルが複雑になりがちです。Web UIを活用することで、初期段階での混乱を最小限に抑えられます。


### フォルダ構成とコアコードの生成

- **プロジェクトの骨格を構築**：Web UIで基本的なフォルダ構成やコアとなるコードを生成させることで、プロジェクトの土台をしっかりと作り上げます。


## ステップ2：clineに生成物を投入する

次のステップでは、ステップ1で作成した構成やコードを**cline**に取り込み、さらに開発を進めます。


### コスト削減

- **効率的なリソース使用**：前段階で試行錯誤を行っているため、clineでの作業コストを削減できます。


### 不足部分の補完

- **自動補完機能**：clineは足りない部分を自動的に補完してくれるため、開発効率が向上します。

### 変更ファイルの自動コミットとロールバック

- **リアルタイムのバージョン管理**：clineは変更したファイルをその場で自動コミットしてくれます。
- **安全なロールバック**：万が一問題が発生しても、変更履歴から簡単に元に戻せます。


### ファイル作成とコマンド実行が得意

- **得意分野を活かす**：clineはファイルの作成やコマンドの実行が得意なので、これらの作業を任せると効果的です。


## 実践的な開発手順の解説

具体的な例として、マスク画像と入力画像を使用してヘッダー画像を生成するツール「**pic-to-header**」を開発します。

### ステップ1：要件を固める

#### プロジェクトの概要

- **言語**：Python
- **目的**：マスク画像と入力画像を合成し、ヘッダー画像を生成する
- **最終目標**：Webアプリとパッケージとして配布

#### ディレクトリ構成の設計

```bash
pic-to-header/
│
├── pic_to_header/
│   ├── __init__.py
│   ├── core.py
│
├── tests/
│   ├── __init__.py
│   └── test_core.py
│
├── web_app/
│   ├── app.py
│
├── requirements.txt
├── README.md
└── .gitignore
```

#### コア機能の実装（`core.py`）

```python
import cv2
import numpy as np

def process_header_image(input_image_path, mask_image_path, output_image_path):
    # 入力画像を読み込む
    input_image = cv2.imread(input_image_path, cv2.IMREAD_UNCHANGED)
    
    # マスク画像を読み込み、グレースケールに変換
    mask_image = cv2.imread(mask_image_path, cv2.IMREAD_GRAYSCALE)
    
    # マスク画像を入力画像と同じサイズにリサイズ
    mask_image = cv2.resize(mask_image, (input_image.shape[1], input_image.shape[0]))
    
    # 入力画像にアルファチャンネルがない場合は追加
    if input_image.shape[2] == 3:
        input_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2BGRA)
    
    # マスクを適用
    input_image[:, :, 3] = mask_image
    
    # 結果を保存
    cv2.imwrite(output_image_path, input_image)

    return output_image_path
```

### ステップ2：clineに生成物を投入する

#### ディレクトリとファイルの自動生成

clineを使用して、必要なディレクトリとファイルを自動的に作成します。

```bash
mkdir pic_to_header
touch pic_to_header/__init__.py
touch pic_to_header/core.py
mkdir tests
touch tests/__init__.py
touch tests/test_core.py
mkdir web_app
touch web_app/app.py
```

#### コードの実装と修正

- **`core.py`にコードを追加**：ステップ1で作成したコア機能を追加します。
- **`requirements.txt`の更新**：必要なライブラリを追加します。

```bash
opencv-python==4.5.5.64
numpy==1.21.5
streamlit==1.10.0
```

#### Webアプリケーションの実装（`web_app/app.py`）

ユーザーの指示により、**Streamlit**で実装します。

```python
import streamlit as st
import os
from pic_to_header.core import process_header_image

def main():
    st.title("Pic-to-Header")
    st.write("マスク画像と入力画像をアップロードして、ヘッダー画像を生成します。")

    input_image = st.file_uploader("入力画像をアップロード", type=["png", "jpg", "jpeg"])
    mask_image = st.file_uploader("マスク画像をアップロード", type=["png", "jpg", "jpeg"])

    if input_image and mask_image:
        if st.button("ヘッダー画像を生成"):
            # 一時ファイルとして保存
            input_path = f"temp_input.{input_image.name.split('.')[-1]}"
            mask_path = f"temp_mask.{mask_image.name.split('.')[-1]}"
            output_path = "output_header.png"

            with open(input_path, "wb") as f:
                f.write(input_image.getbuffer())
            with open(mask_path, "wb") as f:
                f.write(mask_image.getbuffer())

            # 画像処理
            process_header_image(input_path, mask_path, output_path)

            # 結果を表示
            st.image(output_path, caption="生成されたヘッダー画像")
            
            # ダウンロードボタン
            with open(output_path, "rb") as file:
                st.download_button(
                    label="ヘッダー画像をダウンロード",
                    data=file,
                    file_name="header_image.png",
                    mime="image/png"
                )

            # 一時ファイルを削除
            os.remove(input_path)
            os.remove(mask_path)
            os.remove(output_path)

if __name__ == "__main__":
    main()
```

#### ユニットテストの追加（`tests/test_core.py`）

```python
import unittest
import os
import cv2
import numpy as np
from pic_to_header.core import process_header_image

class TestCore(unittest.TestCase):
    def setUp(self):
        self.input_image_path = 'test_input.png'
        self.mask_image_path = 'test_mask.png'
        self.output_image_path = 'test_output.png'

        # テスト用の入力画像を作成
        input_image = np.ones((100, 100, 3), dtype=np.uint8) * 255
        cv2.imwrite(self.input_image_path, input_image)

        # テスト用のマスク画像を作成
        mask_image = np.zeros((100, 100), dtype=np.uint8)
        mask_image[25:75, 25:75] = 255
        cv2.imwrite(self.mask_image_path, mask_image)

    def tearDown(self):
        # テスト用のファイルを削除
        for file in [self.input_image_path, self.mask_image_path, self.output_image_path]:
            if os.path.exists(file):
                os.remove(file)

    def test_process_header_image(self):
        # 関数をテスト
        process_header_image(self.input_image_path, self.mask_image_path, self.output_image_path)

        # 出力ファイルが存在するか確認
        self.assertTrue(os.path.exists(self.output_image_path))

        # 出力画像の検証
        output_image = cv2.imread(self.output_image_path, cv2.IMREAD_UNCHANGED)
        self.assertEqual(output_image.shape[2], 4)  # アルファチャンネルを含むか

if __name__ == '__main__':
    unittest.main()
```

#### 変更ファイルの自動コミットとロールバック

clineを使用して、変更内容を自動的にコミットします。

```bash
git add .
git commit -m "🚀 feat: pic-to-headerの初期実装

- 画像処理機能の実装
- Streamlitアプリケーションの実装
- 依存関係の更新
- README.mdの更新
- ユニットテストの追加

この実装により、マスク画像と入力画像からヘッダー画像を生成する基本機能が完成しました。"
```

万が一問題が発生した場合は、変更履歴から簡単にロールバックできます。


## まとめ

**ChatGPT**や**claude.ai**といったWeb UIベースのAIと**cline**を組み合わせることで、コストを抑えつつ高精度な開発が可能になります。

- **ステップ1**では、定額制のWeb UIを活用して要件を固め、プロジェクトの骨格を作成します。これにより、初期段階での試行錯誤をコストを気にせず行えます。
- **ステップ2**では、clineを使用して不足部分を補完し、開発効率を向上させます。ファイル作成やコマンド実行が得意なclineに任せることで、作業を自動化し、リアルタイムのバージョン管理も可能になります。

ぜひ、この手法を活用して効率的な開発を実現してください。


## リポジトリ

https://github.com/Sunwood-ai-labs/pic-to-header

## CLINE のおすすめシステムプロンプト

https://github.com/Sunwood-ai-labs/MysticLibrary/blob/main/prompts/coding/CLAUDE-DEV-SYSTEM-PROMT-PS.md


<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>