ようやくClineに触れることができた
1. はじめに
みなさん!Vibeコーディング楽しんでますかー??
私は「コーディング中に不明点をChatGPTに投げる」程度の生成AI活用はしていたのですが、「AIエージェントを使用して実際にコードを書いてもらう」ということはなかなか手を出せずにいました。
個人的にClineのようなAIエージェントに手を出せていなかった原因は、
- 過去にAWSの従量課金で月3000$を溶かしたことがあるので怖くて手を出せなかった。
- 他の複数の生成AIサービスに課金をしており、何にどのくらい課金しているのか管理するのが面倒に感じていた。
- 業務内容的に使用できない。
- プログラムはやっぱり人が書かなきゃいけないんだよっ!!!!!!!!!(言い訳)
- モンハンワイルズ楽しい(!?)
などが挙げられます。正直枚挙に暇がないです。
要するに現実逃避をしていました、、、もしかしたら共感していただける方がいるかもしれません。
しかし、先日クラメソさっぽろIT勉強会 (仮) #9: AI 駆動開発に参加し、様々なAI開発の事例を聞き、いい加減重い腰を上げてやらなきゃいけないなと危機感を感じました。
(危機感持つの遅いですね、、、反省しております、、、、)
というわけで、初めてClineを触ってみた様子を記録がてら記事として残そうと思い、本記事を執筆致します。
私と同じように腰が重いエンジニア達が、本記事でAIエージェントを触るきっかけとなってくれれば幸いです。
2. 前提条件
OS:Windows11
エディタ:Cursor
API Key:OpenAI
3. Clineのセットアップ
3.1. Clineをインストール
まずは何といってもエディタにClineをインストールしなければ何も始まりません。
以下の手順でインストールしましょう。
- Cursorを起動して、左側のメニューの「拡張機能」アイコンをクリック
- 検索バーに「Cline」と入力し、Cline拡張機能をインストール
3.2. API Keyを設定
インストールが完了したら、次にAPI Keyの設定を行います。一応無料でも使用できるのですが、返信速度やトークン数に制限があるので何かのLLMのAPI Keyを使用するのが良いでしょう。
-
インストール後に
CTRL
+SHIFT
+P
を押下してコマンドパレットを開き、
cline: Open in New Tab
を入力してEnter
-
Clineのトップページが開くので、
Use your own api key
をクリックしてください。
-
使用するLLMの種類とAPI Keyの入力フォームが表示されるのでそれぞれを入力しましょう。
(今回私はOpenAIを使用しています。)
これで準備は完了です。
次は実際にプロンプトに指示を打ち込んで作業をしてもらいましょう。
4. 実際にClineを動かしてみる
4.1. Hello World
まずは小手調べに、h1タグでマークアップされた「Hello World」のみが記載されているHTMLファイルを作成してもらいましょう。
プロンプトに以下のように打ち込み実行させます。
現在開いているディレクトリに、HTMLファイルを作成してください。
そしてそのHTMLファイルにh1タグを使用してHello Worldと表示されるように追記してください。
実行させると作業が始まります。
1つのファイルの作成が終了すると、その内容で保存するかどうかの判断をCline側から求めてきます。
save
を押下すると作業が保存され次のタスクに遷移します。reject
を押下すると作業が破棄され再度同じタスクが実行されます。再実行時は初回の作業内容と異なる内容でタスクが実行されます。
ターミナルでコマンドを実行する際も、コマンドを実行してよいかの判断をCline側から求めてきます。コマンドの内容を確認し、問題がない場合はRun Command
を押下するとコマンドが実行されます。
Task Complete
と表示されたら無事作業終了です。作成したHTMLファイルを確認すると無事指示通りのHTMLファイルが生成されていることを確認できました。
4.2. HTMLファイルにアニメーションを追加する
先ほど作成したHTMLファイルにアニメーションを追加してみましょう。新しく作業を始める場合はStart New Task
を押下して新規のスレッドを開きます。
先ほど作成したHTMLファイルに花びらが舞うようなアニメーションを追加します。プロンプトに以下のように打ち込み実行させてみます。
作成したHTMLファイルに対して、画面全体に花びらが舞うようなアニメーションを追加してください。
以下がClineが作成したJavaScriptのソースコードです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<canvas id="sakura-canvas" style="position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:0;"></canvas>
<h1 style="position:relative;z-index:1;">Hello World</h1>
<script>
// Sakura (cherry blossom) petal animation
const canvas = document.getElementById('sakura-canvas');
const ctx = canvas.getContext('2d');
let petals = [];
const PETAL_COUNT = 40;
const PETAL_COLORS = ['#f9c9de', '#f7b7d3', '#f6a6c9', '#f4d1e0'];
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
function randomBetween(a, b) {
return a + Math.random() * (b - a);
}
function createPetal() {
const x = randomBetween(0, canvas.width);
const y = randomBetween(-canvas.height, 0);
const size = randomBetween(16, 32);
const speed = randomBetween(1, 2.5);
const sway = randomBetween(0.5, 1.5);
const rot = randomBetween(0, Math.PI * 2);
const rotSpeed = randomBetween(-0.01, 0.01);
const color = PETAL_COLORS[Math.floor(Math.random() * PETAL_COLORS.length)];
return { x, y, size, speed, sway, swayAngle: randomBetween(0, Math.PI * 2), rot, rotSpeed, color };
}
function drawPetal(p) {
ctx.save();
ctx.translate(p.x, p.y);
ctx.rotate(p.rot);
ctx.scale(1, randomBetween(0.7, 1));
ctx.beginPath();
// Draw a simple sakura petal shape
ctx.moveTo(0, 0);
ctx.bezierCurveTo(p.size * 0.2, -p.size * 0.5, p.size * 0.8, -p.size * 0.1, 0, p.size);
ctx.bezierCurveTo(-p.size * 0.8, -p.size * 0.1, -p.size * 0.2, -p.size * 0.5, 0, 0);
ctx.closePath();
ctx.fillStyle = p.color;
ctx.globalAlpha = 0.85;
ctx.shadowColor = '#f9c9de';
ctx.shadowBlur = 8;
ctx.fill();
ctx.restore();
}
function updatePetal(p) {
p.y += p.speed;
p.x += Math.sin(p.swayAngle) * p.sway;
p.swayAngle += 0.01 + Math.random() * 0.01;
p.rot += p.rotSpeed;
if (p.y > canvas.height + 40) {
// Reset to top
p.x = randomBetween(0, canvas.width);
p.y = randomBetween(-40, 0);
p.size = randomBetween(16, 32);
p.speed = randomBetween(1, 2.5);
p.sway = randomBetween(0.5, 1.5);
p.swayAngle = randomBetween(0, Math.PI * 2);
p.rot = randomBetween(0, Math.PI * 2);
p.rotSpeed = randomBetween(-0.01, 0.01);
p.color = PETAL_COLORS[Math.floor(Math.random() * PETAL_COLORS.length)];
}
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (const p of petals) {
updatePetal(p);
drawPetal(p);
}
requestAnimationFrame(animate);
}
petals = Array.from({ length: PETAL_COUNT }, createPetal);
animate();
</script>
</body>
</html>
HTMLファイルを開いてみると、無事花びらが舞うアニメーションが実装されていることが確認できます。
4.3. 簡単な関数とそのテストコード
それでは次にTypeScriptで簡単な関数を定義させ、そのテストコードを併せて実装してもらいましょう。
プロンプトに以下のように打ち込み実行させます。
TypeScriptで次の要件を満たす関数を作成し、そのユニットテストコード(Jest形式)も作成してください。
【関数の目的】
- 文字列を逆順に並べる
【入力】
- `input: string` - 対象の文字列
【出力】
- `string` - 逆順に並んだ文字列
【補足要件】
- 空文字列が渡されたら空文字列を返す
【テスト要件】
- Jestでのユニットテストを記述してください。
- 少なくとも3パターン以上のテストケースを含めてください。
- 正常系と異常系(例:undefinedやnullなど)を含めてください。
コードはすべてTypeScriptで記述し、関数とテストは別々のファイルに記載する形で出力してください。
生成された関数
/**
* 文字列を逆順に並べる関数
* @param input - 対象の文字列(string以外も受け入れ、string以外はTypeError)
* @returns 逆順に並んだ文字列。空文字列なら空文字列を返す。
*/
export function reverseString(input: any): string {
if (typeof input !== 'string') {
throw new TypeError('input must be a string');
}
return input.split('').reverse().join('');
}
生成されたテストコード
import { reverseString } from './reverseString';
describe('reverseString', () => {
// 正常系
it('should reverse a normal string', () => {
expect(reverseString('abc')).toBe('cba');
});
it('should return empty string when input is empty string', () => {
expect(reverseString('')).toBe('');
});
it('should reverse a multibyte string (Japanese)', () => {
expect(reverseString('あいう')).toBe('ういあ');
});
// 異常系
it('should throw TypeError when input is undefined', () => {
// @ts-expect-error
expect(() => reverseString(undefined)).toThrow(TypeError);
});
it('should throw TypeError when input is null', () => {
// @ts-expect-error
expect(() => reverseString(null)).toThrow(TypeError);
});
});
関数とそのテストコードの実装が無事完了しました。
では最後にテストコードを実行し、実際に単体テストを実行させてみます。
4.4. テストの実行
プロンプトに以下のように打ち込み実行させます。
作成したテストコードを実行して、テスト結果をmarkdown形式で出力してください。
実行結果
無事テストが終了したことを確認することができました。
5. 終わりに
本記事では実際にOpenAI API Key を使用してClineを動かし、簡単なタスクを実行させて結果を確認してみました。私は今まで触ったことがなかったので、意外と簡単に動かすことができるんだな(使いこなすとなると話は別になりますが)というのが触れたみた所感です。
まだClineに触れたことのない方々!
意外と簡単に動かすことができるのでぜひこの機会に使ってみてはいかがでしょうか!
(さすがに触ったことがないって人はもういないか、、、)
ちなみに今回の作業実行で掛かったコストは$2弱といったところでした。
これが高いか安いかはまだ判断できないのですが、今後積極的に使っていきたいと思います。
次回あたりは設計ー実装-コードレビューの一連の流れを、疑似AI駆動開発で行った記録を記事として出したいなと思っています。
ここまで読んでいただきありがとうございました。
Discussion