Zenn
🦾

Cline / Roo-Codeにおけるコード理解と新規・保守タスクの現状

2025/03/30に公開
42

記事の概要

  1. Clineは構造的に「局所的なコード理解」になる
  2. CursorとWindsurfとは内部的な実装が違い、できることに差がある
  3. デッドコードを把握できないので大規模保守タスクはやめておいた方がいい
  4. 逆に新規プロジェクトやコンテキスト内に収まる開発は向いている
  5. どうしてもClineを使いたい人のための局所的なコード理解を補うTips

以下AIと書いた記事です。
またClineと書いてありますがRoo Codeとここの部分の実装は揃っている(と調べた)ので
Roo Codeと置き換えてもらっても問題ないです。

追記(4/5): Roo Codeはこちらでだいぶこの懸念が対応されています
https://zenn.dev/tesla/articles/4be4ff326e020c


Clineの特徴として、ユーザからのタスク指示に対して必要な情報を段階的に取得するという方針があります。
あらかじめ全プロジェクトを完全にインデックス化するわけではなく、Tree-sitterで各ファイルのAST(抽象構文木)を生成して局所的な構造情報を抽出し、必要に応じてファイルを開いて詳細を確認する手順を繰り返します。
この「必要最小限の情報だけを逐次取得する」アーキテクチャのおかげで、コンテキストウィンドウ(LLMが一度に扱えるトークン数)の制限をある程度回避でき、巨大なリポジトリでも段階的にコードを読み進めることが可能になります。

しかし、こうした局所解析ベースの仕組みゆえに、Clineが得意なタスクと苦手なタスクが明確に分かれます。本稿では、Clineの設計上どのような場面で強みを発揮し、逆にどういったタスクには向いていないのか、さらに今後の改良の余地についても考察します。


Clineのアプローチ:Tree-sitter+LLMの逐次的なコード理解

1. 全体インデックスではなく「必要最小限の情報」を取得

Clineはプロジェクト開始時に、以下のようなステップを通じてコードを扱います。

  1. ファイルの走査と対応するTree-sitterの読み込み
    対象の言語パーサ(WASM)をロードし、対応するファイル群のASTを生成できるように準備する。
対応箇所
  1. トップレベルのシンボル(関数やクラス)一覧の取得
    list_code_definition_namesなどの機能(ツール)を用いて、各ファイル内で定義されているシンボルを抽出し、コード構造の“概要”をLLMに提供する。
対応箇所
  1. 必要に応じた詳細閲覧
    ユーザが特定のバグ修正や小機能追加を指示した際、LLMは「関連しそうなファイルのシンボル」を確認して、そのファイルのみをread_fileで開き、内容を読み込む。
対応箇所
  1. 部分的なコード編集(ツール呼び出し)
    修正・更新が必要な箇所を特定したら、write_to_filereplace_in_fileなどのツールを使って該当コードを修正する。
対応箇所

このように、「最初にプロジェクト全体を完全にインデックス化して構造把握する」のではなく
必要に応じて局所的にASTやファイル内容を参照する方針です。
結果として、LLMのコンテキストウィンドウが限られていても、不要なコードを読み込まずに済むため、大規模リポジトリでも操作可能になるというメリットがあります。

DeepResearch

2. 局所スコープでの補完・修正に強み

局所的なコード情報を扱う設計は、単一ファイル内または少数のファイルにまたがる軽微な保守・機能追加に非常に向いています。たとえば「このファイルのクラスにメソッドを追加したい」「単純なバグを修正したい」というようなタスクでは、Clineは素早くTree-sitterの情報を参照し、LLMが対話的に修正案を生成してファイルを書き換えられます。局所スコープゆえにトークン数が増大するリスクも低く、モデルが扱いやすい範囲です。
さらに、Clineはツール呼び出し形式の対話を行うため、LLMが誤って余計なファイルを編集したり、危険な操作を実行しないようユーザが途中で承認・キャンセルできる仕組みも備えています。このようにピンポイントの改修や簡単なリファクタはClineが得意とするところだと考えられます。

大規模リファクタリング・保守が苦手な理由

通常のClineで苦手なことを以下に記します。
ただ後述するTipsで多少改善の余地があります。

1. 全体インデックスの欠如

Clineには全ファイルをまとめた依存関係グラフ包括的なシンボルテーブルを作る仕組みが基本的にありません。Tree-sitter解析はファイル単位で完結し、複雑な間接依存関係や、プロジェクト全体のアーキテクチャを自動的に可視化・管理する部分が存在しないのです。そのため、全体的なコード再編成や構造変更を行おうとすると、モデルが依存箇所を見落とすリスクが高まり、誤った修正提案につながりやすくなります。

2. 大規模保守に必要な意図や設計の理解が不十分

保守タスクでは、単なるコードのシンタックス情報だけでなく、モジュールやクラス間の設計意図、ビジネスロジック上の目的など、より深いレベルの理解が必要になるケースが多いです。ClineはTree-sitterを活用して構文情報を抽出する一方で、実装者の設計意図や長期的な拡張性といった概念的情報は、人間が明確にモデルへ伝えない限り、LLMが推測に頼る部分が大きくなります。
特に大規模リファクタリングでは、プロジェクト全体の設計ポリシーを熟知していなければ判断できない変更が多く、それをすべてClineに自律的に任せるのは危険度が高いわけです。結果として、保守タスクはどうしても人間が大まかな指示や方針決定を行う必要があり、Clineは補助的な役割に留まることになります。

ここがcursorやwindsurfと違うところで
cursorやwindsurfは継続的にコード全体を認識してindexingしています

https://docs.cursor.com/context/codebase-indexing
https://codeparrot.ai/blogs/a-guide-to-using-windsurfai

そのため雑に指示して調べてもらっても、@codebaseなどの機能を使っているときは
ローカルのindexingを参考にして大域的に問題を理解することができます。

またwindsurfでもAST解析の仕組みはそれぞれ行っているようです
https://x.com/windsurf_ai/status/1893808444039385239
(おそらくcursorでも似たようなことをしているとは思います)

余談

余談ですがContinueはコード全体をindexingしています。
あんまり使ったことないのでわかりません...
https://github.com/continuedev/continue

雑に調べたDeepResearchを置いておきます
https://note.com/delta_ipsilon/n/n429bbdd43e60

3. デッドコード検出やクロスファイル最適化が困難

デッドコードや不要なモジュールを洗い出すには、コードの利用状況を全体的にスキャンし、間接的に参照されていない箇所を見つける必要があります。Clineは、ASTに基づく構造理解があっても、どのファイルが実際にどこから参照されているのかを全自動で突き止める仕組み(全体インデックスや厳密な依存グラフ生成)は原則として持っていません。
したがって、「モジュールAがプロジェクト全体で本当に使われていないのか?」というような大きな視点の検証をするには、Clineが局所的に読み込むだけでは足りない場合が多いです。ユーザがLLMに「search_filesを使って参照箇所を探してみて」といった明示的な指示やPromptの追加などをし、さらに見落としのないよう範囲を拡張する工夫が必要になります。

つまりClineでは構造上ドライバー席を譲ったとしても地図を見ながら「正確に」道案内する必要があります。

新規プロジェクトや小規模開発への適性

一方で、新規プロジェクトや比較的小規模なコードベースであれば、Clineの局所的な解析方式でも全体を把握しやすく、ほぼ全体をLLMのコンテキストウィンドウ内で扱える可能性が高まります。そうなるとClineは以下のようなメリットを発揮しやすくなります。

  1. 初期設計支援
    新規プロジェクトはコード規模が小さく、設計・実装のすべてをLLMに提示しやすいため、最初のスケルトンや基本モジュールの追加などを効率的に支援可能。
  2. 素早い試行錯誤
    まだコード依存やアーキテクチャが複雑ではないため、Clineが局所的にAST情報を扱うだけで十分にプロジェクト全体を俯瞰でき、リファクタもさほど大掛かりにならない。
  3. ユーザ主導の明確な方針
    新規プロジェクトでは開発者自身が明確な設計イメージを持っている場合が多く、Clineはその指示をサポートする補佐ツールとして最適に機能する。

このように、プロジェクト全体を単一のLLMコンテキストで扱える規模であれば、「全体のインデックスの欠如」は目立たないため、Cline特有の逐次的アプローチが活きます。

また1ファイルが大きい時のリファクタなども有効です
https://x.com/laiso/status/1898677800325808286


Clineをより効果的に使うための情報補完(Tips)

以下では、tree-sitterと今のClineの仕組みから考える
Clineを保守ややや大きめのリファクタリングにも活用したい場合に、ユーザやチームがあらかじめ提供・整備すると良い情報や実践的なテクニックをまとめます。

1. ドキュメントコメント・アノテーション

  • クラス・メソッドの目的
    ASTからはシンボル名や構文構造は分かっても、関数やクラスの「役割」や「設計意図」は把握しきれません。コード内にドキュメントコメント(JSDocやDocstringなど)を記述し、引数の意味や戻り値、利用例などを簡潔に書いておけば、Clineが読み込んだ際にLLMが意味を推測しやすくなります。
  • TODOコメントやFIXMEタグ
    コード内のTODOコメントを明示的に残しておくと、Clineが検索やAST走査でそれらを検出し、問題箇所や改善点を優先的に提示できる可能性が高まります。

事前に仕込んでおく = 影響範囲を自分で把握しているということなので小規模のプロジェクトを扱う時と同じような気持ちで扱えると思います。

2. 小規模な依存関係の明示化

  • simple dependency mapの共有
    プロジェクトで重要なモジュール同士の依存関係や、アーキテクチャのレイヤー構成があれば、簡易的な図やマニュアルを作成しておき、Clineにその情報を含むファイル(例:docs/dependency_overview.md)を読み込ませるよう促すのも有効です。LLMが「このドキュメントに書いてあるアーキテクチャ上の制限を守らないといけない」と理解し、リファクタ案を提案するときに考慮する可能性が高まります。

  • .clinerulesでプロジェクト独自ルールを定義
    Clineでは.clinerulesファイルやディレクトリに、依存関係上の禁止事項やファイルの取り扱い方針などをカスタム命令として書けます。モジュールAとモジュールBの相互依存を避ける、といったルールを簡単に明文化しておくと、LLMはそれを破らないように行動します。

3. タスクの分割と明確化

  • 大規模リファクタリングを小さなステップに分解
    「このモジュール内のデッドコード削除」→「モジュールXが依存している箇所を調整」→「テストを通過させる」…といったステップに分割し、それぞれを個別のタスクとしてClineに指示すると、局所スコープの強みを活かせます。
  • 作業範囲を明示する
    「このフォルダ以下のコードのみを編集して」と具体的に範囲を限定すると、LLMが無関係な箇所まで修正してしまうリスクを減らせます。

過去記事でも同様に述べています
https://zenn.dev/tesla/articles/ade9883b2f62c9

4. 手動インデックス化ツールの活用

  • 依存関係クルーズツール
    dependency-cruiserやmadgeなどを別途実行し、その結果を参照しながらリファクタ範囲の影響を推定できます。Cline単体にはない依存関係解析を補完できるため、全体的な構造変化の際に役立つでしょう。
  • 人間が要約したメモの提供
    完全自動のインデックスではないですが、開発者がプロジェクト構造のメモをまとめ(主要機能・依存関係・デザインパターンなど)、Clineに読み込ませるだけでも、LLMの推論が格段にスムーズになります。

diniiさんのこの辺も参考になると思います
https://zenn.dev/dinii/articles/readable-code-explained-in-dep-graph

5.gitログからのHotspot分析

  • 頻繁に変更されるファイル・メソッドの特定
    保守やリファクタリングの優先度を決めるために、gitのログを解析して「どのファイルがよく変更されているか」「どのメソッドがバグ修正の履歴が多いか」を調べる手法があります。
    例えばgit logの履歴をスクリプトで集計し、変更回数やコミット数の分布を数値化することで、**「ホットスポット(変更頻度が高くバグが発生しやすい箇所)」**を特定できます。

  • 統合的なリファクタ計画
    ホットスポット分析を通じて優先的に改修すべき箇所を明確化してから、小さなステップに分けてClineに取り組ませれば、局所スコープを得意とするClineの特徴をうまく活かしつつ、重要箇所から優先的に手を入れるリファクタリングが実現しやすくなるでしょう。

新規作成時はCheckpoint機能以外に細かくcommitするようにして、そのcommit履歴から判断したり
あるいは既存のプロジェクトのgit logから分析してもらったその結果をmdにまとめておくなど

6. 長期運用時のコツ

  • 定期的なクリーンアップとレビュー
    Clineが行った修正や、自動生成されたコードを後日見直して、不要な箇所を削除したりコメントを追記するなど、メンテナンスのサイクルを取り入れる。
  • Cline側の設定ファイルやプロンプトのアップデート
    プロジェクトが大きくなるほど、.clinerulesファイルやカスタム命令、ツール説明のバージョン管理が重要になります。アップデートを怠ると、新たな規約やディレクトリ構造がLLMに正しく伝わらず、誤った修正提案につながります。

(推測)Devinについてのおまけ

この辺の記事から多分Devinもいい感じにコードを押さえられてないので
メインはtree-sitterのような局所的な理解に留まる可能性があります
(そもそもコード全体を把握することにおけるコンテキスト長の圧迫があるという問題はありますが...)

https://tech.medpeer.co.jp/entry/technical-debt-with-devin#うまくいかなかった指示の例

まとめ

Clineは局所的なAST解析と逐次的ツール呼び出しに強みを持つため、コード規模が大きくなっても一定の柔軟性を維持して自動生成や修正を行うことができます。ただし、全体の依存関係や大規模リファクタなどには弱いため、追加的な情報やルールをあらかじめ準備・明示することで、Clineの性能を引き出すのが重要です。

  • ドキュメントコメントや.clinerules、依存関係マップなど、構造的・設計的な情報をClineが認識できる形で補完する。
  • リファクタリング作業を小さなタスクに分割し、明確な指示とテスト結果をこまめにフィードバックする。
  • 静的解析ツール、依存クルーズツールのログを読み込ませる。

これらを実践すれば、局所的な強みを活かしつつ、Clineによる自動化の範囲を徐々に拡大できるでしょう。結果として、LLMに「こんなコード変更をして」と投げるだけではなく、人間がプロジェクト構造や意図を積極的に教えてあげることで、Clineはより正確で用途に合ったリファクタ・保守タスクの提案を行うことが可能になります。

(この辺のサーベイもあるのですがちょっと力尽きたので次回...)

終わりに

ここからは個人の感想になります
おそらく実装的にはtree-sitterのようなAST理解 + codebaseのindexingがあるので
CursorやWindsurfの方が優れていると思います。

  • 気軽に使いやすいUI設計
  • VSCodeから追加してAPIキーを設定するだけ
  • Cursorとは違い直で各LLMプロパイダと接続できる
  • MCPに関する実装周りの充実感
  • ちゃんとプロンプト周りを把握して実装できる

などClineにしかないものもあります。
(Auto ApproveはYOLOモードなどで実装されているので対象外です)

自分は新規で適当に作りたいときClaudeで計画を立てて
Clineの方がなんとなく早いとか指示が通るなと感じるのでその計画をもとに
Clineでざっくり動く最小限のプロトを作ってから
Cursorで全体的に整えていくという手法をとっています。

この辺のvibe codingの手法的なものもそのうち書きたいな〜と思っています。

よければXのフォローお願いします!
https://x.com/tesla0225

42

Discussion

ログインするとコメントできます