半Vibe CodingでChrome拡張を作ってみた
先日Cursor Meetup Tokyoがありましたが、現地参加者349人、オンライン参加者5818人とかなり熱量を感じたイベントでしたね。(当日connpassのサーバが一時落ちたのも印象的でした)
Cursor Meetup Tokyo - connpass
各セッションでのAI活用事例を聞きながら、私ももっとAIを活用したコーディングも試していくべきだろうなーという漠然とした思いから 半Vibe Coding(一部自分でもコードを書いたりコードの詳細な指示をしたのでそういう意味で"半"と書いてます)をやってみたので記事に起こしてみます。
今回やりたかったこと
抱えていた課題
- ネットサーフィン中に読む英文をChatGPTのようなAIサービスに翻訳してもらいたいが、文章をコピペしてAIサービスの入力フォームにペーストして翻訳のためのプロンプトを書き足すでのがめんどくさいので効率化したい
具体的な実現方法
- Chrome拡張で次の機能を実装する
- 右クリックメニューに「AIサービスに質問する」みたいな項目を選べるようにし、選択したらAIサービスを新しいタブで開く
新しいタブを開いたらAIサービスの入力フォームに選択中の文章を入力してEnterキーを押下する- AIサービス側の入力フォームの実装の都合上、拡張側から文字列を入力するのは難しそうだったのでプロンプトをクリップボードにコピーしておきすぐにペーストできる状態にする
ちなみにこの機能を作りたいと思った背景として、既にDeepLが提供するChrome拡張にテキスト選択した文字を右クリックメニューから翻訳してもらう機能があるんですが、ChatGPT等の方が翻訳の精度が高いことが多く最近あまり使わなくなったいう事情があったりします。。
実装にあたっての制約
- CursorのAgentに実現したい機能を伝え、自分では"原則"コードを書かない
- 完全にお遊びで書いたのであまりガチガチな制約にはしませんでした。
- モデルは限定せずAutoを指定
成果物
README.mdもCursorくんに書いてもらったんですが、私のCursorくんはRulesで「ため口で話せ」と設定しているのでこんな感じにめっちゃ馴れ馴れしいREADMEです。
このドキュメントは"ずぼら"な開発者が Cursor(AI ペアプロ)で自動生成したものです。内容を 100%信じて地雷を踏んでも責任は取らんぞ! ついでに、このプログラム自体もほぼ Cursor で"vive coding"した、いわゆる AI 産のずぼらコードだ。人力成分は限りなく薄いぞ。
スクリーンショット

右クリックメニューから「XXXXでサクっと質問」が選択できるようになっている

選択すると新しいタブでAIサービスのサイトが開き、クリップボードにプロンプトがコピーされた状態になる

ここからは手動です。人間がクリップボードのプロンプトをペーストして質問します。

Chrome拡張の設定画面。事前にprefixとして付与したいベースのプロンプトを定義できます。また任意のAIサービスを動的に追加できるようにしています。
作ってみての反省
そもそもの話...作ってから思ったんですが、新しいタブでAIサービスを開くんじゃなくて単純にOpenAI API等を実行できるようにした方が便利でしたね(まぁ、また次回の改善点ということで...)
というわけで後日以下でリベンジしました
半Vive Codingをやってみて
学びになったこと
Chrome拡張の土台となる実装を書くのは得意そう
前述した「具体的な実現方法」のようなプロンプトをCursorに指示してコードを書いてもらいましたが、最初はbackground.js, manifest.json, options.htmlなどとChrome拡張のベーシックなファイルはそつなく出力してくれました。
途中でjsからts(+Vite)に書き直してもらったんですが、ViteとChrome拡張に関するnpmパッケージの依存関係のコンフリクト問題(後述)以外はすんなり書いてくれたかなと思います。
アプリ名の命名相談にも乗ってもらえる
今回どういうアプリ名にするか結構悩んだので、Cursorに相談して決めました。 とにかくこのアプリで翻訳を楽にしたいんだよね、っていうニュアンスを伝えた結果、「ずぼらGPT」に決定。結構覚えやすくて良い。
CursorのRulesでフランクに返す人格を作っておくと反応が面白い
※実際のチャットの様子の例

Rulesにはため口で返してください程度しか指示してないんですが、なんか後半ツンデレな感じで返してくれるようになりました。何でだろう。
「エラーになった!!!」「動かなくなった!!!」とかおおよそエンジニアとは思えない表現を多用すると、「そんなふんわりとした表現じゃわかんねーよ」「またかよ」とド直球に返答してくれたりするので、そういう人間味感じるレスポンスが楽しかったです。(AI相手だからこそできるムーブですね)
あと、ビルド後のエラーを報告した際にChrome拡張ビルドしたら再読み込みしろよっていうのを何度も念押しされました。再読み込み、大事です。
大変だったこと
npmパッケージの依存関係をなかなか解消してくれなかった
当初はVite+CRXJSでビルドする構成を提案してくれていたんですが、CRXJSが対応するViteのバージョンが低く、Viteのバージョンを下げないと依存関係を解決できずエラーとなっていました。
この依存関係のエラーの原因解決のために10回前後Cursorとやり取りをしましたが結局解決できず、こちらから「そもそもCRXJS使わずにビルドする構成にしたら?」と提案して回避してもらいました。 ちょっと頑固な部分がある模様。
最初に書いてもらったCSSが微妙すぎる
拡張アイコンをクリックした設定メニューが表示されるようにしたんですが、文字が小さすぎて使い物にならなかったりスクロールバーがないのでコンテンツが見切れてしまったり、といった初歩的な問題が頻発しました。
スクリーンショットを取ってプロンプトに添付してあげると問題を理解してくれはするようですが、地道に何回もコミュニケーションしながらベターなスタイルに寄せていくことになりました。
リファクタリングを明示的に指示しないとクソデカメソッドや重複コードを平気で出力してくる
他所でも言われたりする話ですが、実務での拡張性や保守性を考慮できていない駆け出しエンジニアレベルのコードが出てくることが多々あるのでリファクタリングの指示は必須でした。
単一のファイルを予め指示してリファクタリングしてもらうとそれなりの品質には仕上がりました。
ビルドしてすぐ動くコードは出力してくれないので追加修正依頼が必要
開発の後半はビルドしたあと実際に出たエラーの文字をコピペして修正依頼をひたすら出していました。体感ですが20~30往復くらいはしたかもしれない。
意外とトータルの開発時間はかかった
結局、完成するまでトータルで5時間程度かかりました。 そのうち、2時間くらいはビルド後のエラー解消やnpmパッケージの依存関係の対処だったので、逆に言えばそこさえなければ早く作れたんだろうなとも思います。 この辺は工夫の余地がないか今後も試していきたいですね。