Cursor / Cline / Devin / ClaudeCode MEMO

試せてないけど、知見っぽいやつをメモっておく。

- プロジェクト直下に
/docs
や/knowledge
的なディレクトリを作って開発に関する知識で必要なものがあったらここを参照させるようにする。- ex. ディレクトリの構成(プロジェクト内のどこにどういうファイルがあるかを示す)
- ex. テストコードの書き方
- ex. コードを通して実現しているサービスの概要(ドメイン知識)
- 学んだことを自分で整理させて、自分でファイルにまとめさせる。既存に学んだことで更新する必要のある部分だけ更新する。
- mizchiさんの
.clinerules
- 『Clineに全部賭ける前に 〜Clineの動作原理を深掘り〜』記事の「Clineを最大限活用するために」というセクションの部分大事。

TODO
-
.clinerules
や.cursorrules
の充実(.cursorrules
は、Project Rulesの方が主流なようなのでそっちを中心に)- サービス概要など
- MCPについての理解を深めるために何か一つMCP接続した作業をしてみる。
- 読めてない読みたいもの
- https://zenn.dev/koichi_51/articles/29f502f24e4986
- https://zenn.dev/shosampo/articles/cursor-advanced-techniques
- https://note.com/nike_cha_n/n/ndf25541beba2
- https://note.com/nike_cha_n/n/nd0f7566019ae
- https://zenn.dev/ks0318/articles/b8eb2c9396f9cb
- https://zenn.dev/berry_blog/articles/c72564d4d89926
- https://zenn.dev/globis/articles/cursor-project-rules
- https://zenn.dev/heavenosk/articles/cline-plan-mode
- https://note.com/unikoukokun/n/n3977a603633c
- https://zenn.dev/razokulover/articles/768337f838a110
- https://zenn.dev/tkwbr999/articles/41a522427a3764
- https://zenn.dev/watany/articles/85af6cfb8dccb2
- https://zenn.dev/watany/articles/50665ee40f4948
- https://zenn.dev/mkj/articles/cf8536923d9cd7

Cursorの共通ルールであるRules for AIにgit push --forceは使わないこと
と書いていても、平気で使うことがある。
Cursorの自動実行コマンドホワイトリストとブラックリストを活用して、元々ホワイトリストにgit
のように入れていたものを、具体的にgit status
などのように許可する具体的なコマンド名を追加していくホワイトリスト方式で試してみつつ、加えてブラックリストも厳密に設定するようにする。

Cursor指示出しちゃんとしないと作業しすぎるな。
リファクタリングしようと思うのでまずはテストから書き始めよう、と言っただけで、
- 👀テストパッケージのインストール
- テストセットアップファイルの作成
- テストコンフィグファイルの作成
- 👀テストコードファイルの作成
- テストコードの実装
- テストコードの実行&確認
- 👀リファクタリング対象のコードのリファクタリング作業(ファイル切り出しなど)
- テストコード実行&確認
これぐらいの作業を一気にやっちゃう。
個人的には、👀の箇所ぐらいで「このパッケージを使おうと思うんですけどいいですかね?」、「こういうテストをこれから書こうと思うんですけどどう思いますかね?」、「リファクタリング作業としてこれを切り出そうと思うんですけどどうですかね?(むしろこれが一番最初か、どういう方針でリファクタリングしようとしているのか)」みたいなことを都度確認してもらえると嬉しいなと思った。
全部の作業終わってからこっちが最終確認だと、色々間のコンテキスト分からなくて実装差分だけ見ても分からない。都度レビュー大事だな。この点Clineの方がタスクを1つずつ着実にこなして、都度確認求めてくるのが合ってて好きかもなあ(Clineはauto approve使ってないからってのもある。Cursorに色々コマンド自動許可し過ぎなのかも)
ただあれだな、 テストを自動で実行して確認してくれるのはいい感じだな。

AIが書いてくれたコードについて、自分が理解できていない場合、レビューのしようがなくなる。
Vitestのテスト実行時、以下の箇所で一生詰まっていた。
FAIL src/__tests__/hooks/useSelectedText.test.ts [ src/__tests__/hooks/useSelectedText.test.ts ]
Error: Failed to resolve entry for package "@raycast/api". The package may have incorrect main/module/exports specified in its package.json.
❯ packageEntryFailure node_modules/vite/dist/node/chunks/dep-B0fRCRkQ.js:19549:15
❯ resolvePackageEntry node_modules/vite/dist/node/chunks/dep-B0fRCRkQ.js:19546:3
❯ tryNodeResolve node_modules/vite/dist/node/chunks/dep-B0fRCRkQ.js:19411:18
❯ ResolveIdContext.resolveId node_modules/vite/dist/node/chunks/dep-B0fRCRkQ.js:19184:19
❯ EnvironmentPluginContainer.resolveId node_modules/vite/dist/node/chunks/dep-B0fRCRkQ.js:47572:17
AIが自力で以下の修正をしてテストが通るようになった。
export default defineConfig({
test: {
environment: "happy-dom",
globals: true,
setupFiles: ["./vitest.setup.ts"],
},
+ resolve: {
+ alias: {
+ "@raycast/api": "./src/__tests__/__mocks__/raycast-api-mock.ts",
+ },
+ },
});
通るようになったが、それを見た自分がなぜこれをしたことによって通ったのかが分からず、この実装が適切なのかどうかの判断がつかなかった。
このあと、ChatGPTと話してこのresolve.alias
の役割について理解したうえで、なぜresolve.alias
の指定なしでは@raycast/api
がテスト実行時にエラーとなるのか、なぜ他のモジュール(ex. next/router)などはこの記載なしでもエラーとならないのか、importの依存解決のタイミングとvitest.setup.ts
の読み込まれるタイミングの違いなどについて色々学んだことで、結果的にAIは正しい実装をしていたことが分かった(しかもこれ以外にはエラー解消できなかったはず)。
この件を通して、「自分がよく分かっていないけど動いてはいる」みたいな状態に対してどこまで自分の解像度を上げる必要があるかについて都度考える必要があるのかななど思った。多分今回のやつも、究極別によく分かっていなくても「まあテストコードだしな」みたいな気持ちで「動いてるからヨシ」って流してしまう気がした。こういう塩梅の見極め・判断がAIコーディング時代においては結構重要になってきそう(何でもかんでも自分も理解している状態になろうとすると時間かかりすぎるので(それでもChatGPTなどのおかげで相当短縮できてはいるが))。
それはそれとして、今回の件についても、自分が事前にresolve.alias
の役割について過去に学んでいたら、「あーあれね、うんうんOK」ってできたはずなので、こういう判断のもととなる知識はどこまでいっても知らないよりは知っていた方がいいなと思った(勉強というか、個人開発とか大事だねみたいな話。今回のこれは個人開発の中で知った知識なので)。

PR作成後、gh pr view
でPR内容を出力するときに、CodeRabbitのコードレビューも出力に含まれるから、そこからCodeRabbitのレビュー事項拾って、「このレビュー事項最もなので修正対応して」って言うの良い体験だな。

Cursor、今のところコンテキストウィンドウをこちらが気にすることなく定額$20で使えてるのありがたいな。Cursor使ってると、ずっと同じAgent Chat上で作業しちゃう。勿論コンテキストの量とんでもないことになってるんだろうけど、定額$20だから気にせずに使い続けられるのいい。
Clineだとどうしても今消費しているコンテキストの量を気にしちゃうから、結構頻繁に1タスクこなすごとに新しくしてたけど、Cursorはその煩わしさを現状気にしなくていいのが良い点(まあ膨大なコンテキストを使い続けるのは回答精度が落ちるみたいな話もあるのであまり良くないのかもだけど)。Cursorは誰でも使いやすいってのはこういうところもあるかも。

1回YOLO modeのallow/denylistが消失したので今後のためにメモ
allow
- git status
- git log
- git diff
- git switch
- git branch
- git checkout
- git show
- git remote -v
- git fetch
- gh issue view
- gh pr view
- gh pr diff
- find
- pwd
- cat
- cd
- find
- head
- tail
- grep
- ls
- xargs
- sort
- tee
- date
- ps
- which
- npm run test
- yarn test
- yarn typecheck
- make test-file
- repomix
deny
- git add
- git commit
- git push
- git pull
- git merge
- git revert
- git reset
- git branch -D
- gh pr merge
- gh pr close
- gh repo delete
- gh workflow run
- rm
- mkdir
- npm install
- yarn install
3/20
4/20
6/6

MEMO
プログラマ(人間)とAIのやること
- [プログラマ] こういうことがしたい(〇〇の機能を実装したい、新規にテーブルを作りたい)ということを思う(これをまず詳細に言語化できるようにする)
- [プログラマ] AIにそれを伝える(いきなり全て伝えると混乱するので、作業をある程度細かくしたうえで伝えていく。※これについては今こうやっているが、逆にこれがボトルネックとなってAIの力を引き出しきれない可能性もある。ただ、全部丸投げでこれやってと振ってしまったときに、それを最終的にレビューする自分の負担が相当大きくなってしまう(これはちょうど普段の開発でも何も情報共有をせず2000行近いの差分のPRをコードレビュー依頼するようなことに近い)ので、だいぶ考えものではある。)
- [プログラマ] AIに実装方針についてこういうふうに進めようと思うというのを返してもらい、それに対してレビューする(設計的にはそれが理想だけど、現実的なコスパと合わないのでここは省略していいよ、などの人間が判断せざる得ないような機微をこちらが判断し伝える)
- [AI] AIがレビューを受けた実装方針に従って実装する(もうここは勝手にAIが動き続けて成果物を吐き出してくれる)
- [プログラマ] AIが吐き出した差分について、人間が承諾/拒否を判断するし、修正してほしい箇所は指摘する(コードレビューだなこれ)
- [AI] 全て承認したら、AIに作業内容をまとめてもらってコミット及びPRまでを作成してもらう
- [プログラマ] 最後にPR全体を通しでレビューして、OKそうだったら終わり(あるいは二次レビューとしてよりテックリードな人のレビューを受ける)
- [プログラマ] 動作確認してステージングテストしてリリース
マジでレビュワーやなこの世界。これAIコーディングちゃんと活用できる人はだいぶな数AIコーディング中に逐一レビューをすることになるから、必然的にコードの質が上がっていくのかもしれない。しかもAIが書いてるからね(知識量は自分に比べて遥かに膨大なAIが)。

Cursor上からnpx
のみを指定するだけではうまくMCPクライアントの解決ができない問題。
# Nodeへのフルパスを取得 → /Users/{username}/.volta/tools/image/node/22.14.0/bin/node みたいに出る
volta which node
# フルパス最後の`node`部分を`npx`に書き換えてこれをMCPサーバーの`command`に指定する
/Users/{username}/.volta/tools/image/node/22.14.0/bin/npx

Coding with AI Agentの辛いところ
- [Cursor] AI Agentモードで全て設計から実装までをやっていると、設計時点のコンテキストを忘れることがあり、実装フェーズで設計時点のときとは全然違うことをしだすことがある。
- [Cline] それに対して、Clineは計画・実行をステップバイステップで進めてくれるのが、雇用する人間の側から見ると安心感がある(あと多分Clineは計画モードで議論した内容をまとめた上で新たに実行モードで展開しているように見えるから、計画モードで議論した全てのコンテキストを含んでいないことによるやるべきことに集中できる感があるのかもしれない)。Cursorは暴走列車。
- [Corsor] 設計の議論をしているのに、勝手に実装を始めることが多々ある。Clineとの対比が強く出てしまうが、雇用する人間側からすると、ある程度の共有は欲しいというか、勝手に作業を進めすぎないで欲しい感がある。手放しで信頼できるような存在としてCursorのAI Agentをまだ見ることができていない状態から、勝手に色々進めて「できました!」と言われても、偶然できていただけ説を拭いきれない。まだ現段階では人間の目を逐一チェックとして入れておきたい。

GitHub MCP、GitHub CLI(ghコマンド)があるからあまり使い所はないかなと思っていたけど、Rulesにghコマンドを使用できることを記載するより、GitHub MCPを定義しておく方がちゃんと適切に状況に応じてツールを使ってくれる可能性が高まる気がした。
というのも、GitHub MCPを定義せずに、ghコマンドのことをRulesに書いてあるだけだと、PRを見に行ってほしいときにfetch MCPツールを利用してしまって、アクセスできなくて詰んでしまうことが多々あった。

AI Agentぽんこつまとめ
- Webフロントエンドとアプリで同じ作業をしていて、既にPRの作成が済んでいる状態のとき、Webフロントエンドとアプリの実装を進めたので、最新の内容でPRの概要を更新してと頼んだら、WebフロントのPRの方は正しくやってくれたが、アプリの方のPRのURLを指定したにも関わらず、アプリ側のPR番号を使ってWebフロント側の対応する過去のPR番号のPRの概要を書き換えてしまった。

これとても同感。現状どうやってもコンテキストウィンドウにボトルネックがあるから、MCPツールを増やしすぎないとか、カスタム指示を書きすぎないとか、いかにコンテキストウィンドウを節約して1つのタスクに集中させるか(その1つのタスクに関係ある情報のみを必要十分な量だけ入れ込む)が重要。

カスタム指示をリセットしてみる。
各リポジトリごとにエディタ開くようにしてみる(リポジトリをcdで移動させるのが大変そうというか、指示なしで上手いことやってくれる確率が低い)

AIエージェントの理想系は、あらゆるツールを柔軟に使い分けてなんでもこなせる1体の最強万能エージェントだと思うけど、現実問題今現在ではコンテキストウィンドウがボトルネックとなる以上、あらゆる全てのツールの説明をコンテキストに含めつつ、その他リソースの情報も適切に加えて処理させることは現実的じゃないから、必然的にツールを絞る必要が出てくる。となると、コンテキストウィンドウ的な問題が解消するまでは、ツールを絞った用途別のAIエージェントをその用途ごとに複数作ることになりそうで、用途別のAIエージェントが洗練されれば、用途別エージェントを適切に使い分けるAIエージェント(AIエージェントのオーケストレーションみたいな。となると最強のAIエージェントはこのレイヤーか?)が出てくるような未来は見えて、そうなるとGoogleが発表したA2Aのような、エージェントが協調する方向性に進みそうなのは確かになとなる。
というかmastraは複数のAIエージェントを登録できるけど、これはエージェントを呼び出す万能エージェントみたいな構造になっていたりするのか?あくまで同じアプリケーション内で定義したものだけど(さながらfunction callingが初めて出来てLLMからツールが使えるようになった時のように。その後MCPとしてツールが標準化されたように、AIエージェントもA2Aのように標準化されて(実際既にここまで来てる)、ネットワークを介して外部の専用エージェントを呼び出すみたいなことができるようになるのかもしれない)。そう考えると、mastraはAIエージェントというブレイクスルーの入り口なのかも。

AIは、例えばDDD原理主義的な理想的な設計案を提示することは得意だが、コスパを意識した設計案を提示することは苦手。現在の状況を色々考慮した上でのコスパの機微が判断できない。
いくらでも時間使えるならその理想的な設計案で実装した方がいいよね、みたいなのを提案してくることが多い。ここは開発者がちゃんとハンドリングしてどこに落とし所をつけるかを判断することが重要。

ClaudeCode、PhpStorm的な言語化できない良さがある気がするな。
Cursorとモデル的な差異はないから、AIエージェントとしてのプロンプトの組み方が上手いとかなのかな。
ClaudeCodeの辛いところ(対Cursor比)
- Cursorと比べて、部分的なコードを範囲指定して、それをコンテキストに簡単に含めるのが難しい。
AI系ツールの辛いところ(対PhpStorm比)
- ファイルのリネーム作業が激弱