Claude にコードを書き換えてもらう時、型エラーや定義ジャンプ・参照ジャンプまで含めて精度高くやってほしい開発者向け
Claude にコードを書き換えてもらう前提で開発している時、定義ジャンプや参照ジャンプ、型エラーの自動検知を効かせたい場面で使う。具体的には、TypeScript の React コンポーネントの型を広げる、Python のクラスを別構造に作り直す、Rust の所有権周りを直す、OSS の関数の影響範囲を辿る、といった『コードの構造を踏まえた書き換え』を頼む時。Claude 側で能動的に呼ぶことが多いが、まずは該当言語の code intelligence plugin と language server 本体を入れて待機状態にしておく
LSP は、Claude Code が「コードの中身を構造的に読む」ために使う内蔵の道具です。SearchBar という名前の部品がどこで定義されているか、それがどこから呼ばれているか、その変数の型は何か。そういう「コードの地図」を Claude が引いてくる時にこの道具が動きます。地図を出してくれるのは、裏で動いている language server というプログラムです。Claude はそれと会話する窓口を1つ持っていて、その窓口が LSP です。
面白いのは、Claude が能動的に呼ばなくても自動で発火する場面があることです。Claude がファイルを書き換えた直後、LSP が型エラーや警告を Claude に渡します。だから Claude は「ビルドして確認します」と言わずに、その場で間違いに気付いて直せる。これが大きい。
噛み砕くと
言語ごとに「文法に詳しい先生」がスタンバイしていて、Claude が「この単語の正体って何ですか」「これ誰から呼ばれてますか」と聞きにいく。LSP はその先生と Claude をつなぐインターホンみたいなものです。インターホンだけあっても、向こうに先生がいなければ意味がない。だから先生役の language server を別途インストールしておく必要があります。
そして Claude が編集を終えるたび、先生から「ここ型が合ってないよ」と Claude にメモが届く。Claude はそれを見て即座に直す。読者が「ビルドエラー出るんだけど」と毎回貼り付けて教えてあげる必要が、そもそも減ります。
大事な前提:plugin を入れるまで、この道具は完全に黙っています
公式ドキュメントは "The tool is inactive until you install a code intelligence plugin for your language." と明示しています。何も入れていない状態だと、Claude は LSP を呼ぼうとしても返事が返ってこない。エラーすら出ません。ただ「黙って何もしない」状態です。
もう一つ重要なのは、plugin を入れただけでは動かない言語が多いこと。plugin が運んでくるのは language server の設定だけで、language server 本体のプログラムは別途インストールが必要です。TypeScript なら typescript-language-server、Python なら pyright や pylsp、Rust なら rust-analyzer。ここを忘れると「plugin 入れたのに何も起きない」状態になります。
「TypeScript の React コンポーネント <SearchBar> の型を書き換える」を例に、実際の手順を見る
料理レシピを検索する Web アプリを作っていて、トップ画面に置いた検索バー <SearchBar> を直すとします。今は文字列だけ受け取る作りですが、「カテゴリ絞り込み」も受け取れるように型を広げたい。中身は1コンポーネントですが、このバーは検索ページ・トップ・ヘッダーの3か所で使い回されていて、API を叩く関数 searchRecipes にも繋がっています。型を変えると、呼び出し側の3か所と API 側の関数が芋づる式に影響します。Claude にこの作業を頼んだ時、LSP が裏で何をしているかを追います。
ステップ1: 「SearchBar の型を変えたい」と Claude に頼む
普段通り依頼します。
SearchBar の props を { query: string } から
{ query: string; category?: string } に広げて、
カテゴリ絞り込み機能を追加してほしい
ここで Claude が真っ先にやるのは、SearchBar が今どう使われているかを把握することです。
ステップ2: 定義ジャンプ
公式の呼び方は "Jump to a symbol's definition"。Claude は SearchBar がどのファイルで定義されているかを LSP に聞きます。Grep でファイル全体を文字列検索する手もありますが、LSP は「同名の別物」を排除して本物の定義1個に飛んでくれる。たとえばコメントの中の "SearchBar" や、似た名前の SearchBarMobile を取り違えません。
ステップ3: 参照ジャンプ
公式の呼び方は "Find all references to a symbol"。定義場所が分かったら、Claude は「この SearchBar を呼んでいるのは誰か」を全部洗います。LSP が返してくる結果は次のイメージです。
src/pages/index.tsx:14
src/pages/search.tsx:22
src/components/Header.tsx:48
3か所ヒット。Claude はこれを見て「3つ全部の呼び出し側を直す必要がある」と判断します。Grep で SearchBar という文字列を探すと、コメントや別ファイルの import 文も拾ってしまう。LSP は「実際にコンポーネントとして呼んでいる場所」だけを返してくれる。これが地味に強い。
ステップ4: 型情報の取得
公式の呼び方は "Get type information at a position"。Claude は API 関数 searchRecipes が今どんな型を受け取っているかを LSP に確認します。返ってくる型情報はこんな感じ。
function searchRecipes(query: string): Promise<Recipe[]>
これを見て Claude は「category を追加するなら、この関数も (query: string, category?: string) に広げないと型エラーになる」と気付きます。ここで初心者が勘違いしやすいのが、「Claude が空気を読んで賢く判断している」と思ってしまうこと。実際は LSP から型情報を機械的に引いて、その事実をもとに動いています。
ステップ5: 実装の検索と呼び出し階層の追跡
公式の呼び方は "Find implementations of an interface" と "Trace call hierarchies"。もし searchRecipes が RecipeSearcher という interface の実装だった場合、Claude は「他の実装クラスはないか」も LSP に聞きます。テスト用のモック実装が別にあれば、それも一緒に直さないと型が合わなくなる。call hierarchy まで辿れば、searchRecipes を呼んでいる関数の関数まで連鎖的に確認できます。
ステップ6: 編集 → 自動で型エラー報告
Claude が SearchBar の定義を書き換え、呼び出し側3か所を直し、searchRecipes も広げました。書き換えた瞬間、LSP は自動で型チェックを走らせて、Claude に結果を渡します。
src/pages/search.tsx:24 type error:
Property 'category' does not exist on type '{ query: string }'
あ、1か所書き換え漏れがあった。Claude は読者に質問することなく、自力でその行を直します。これが公式の言う "automatically reports type errors and warnings so Claude can fix issues without a separate build step" の正体です。npm run build を読者が手動で走らせて、エラーログを貼り付けて、それを Claude に渡す。そういう往復が消えます。
つまり LSP は何をしてくれるのか
- やってくれる: 定義場所への正確なジャンプ、参照箇所の全件抽出、型情報の取得、ファイル・作業領域内の symbol 一覧、interface の implementation 検索、呼び出し階層の追跡、ファイル編集後の自動型チェック
- やってくれない: コード実行・テスト実行・本物のビルド成果物の生成。あくまで「コードを読んで構造を答える」までで、動かす役は Bash や別の道具の担当
- 意味が薄い場面: language server が成熟していない言語、設定ファイルや Markdown 中心の作業、HTML・CSS のような型システムが薄い領域。これらは Grep や Read で十分
使いどころ3シナリオ
シナリオ1: 既存の TypeScript 製 EC サイトに「お気に入り機能」を足したい
商品カードコンポーネント <ProductCard> に「お気に入り追加ボタン」を入れる依頼。コンポーネントは検索結果ページ・商品一覧・関連商品の3画面で使い回しています。Claude に頼むと、まず参照ジャンプで使われ箇所を洗い、props に onFavorite? を足しても既存の呼び出し側で型エラーが出ないことを確認してから着手します。書き終わったあと、もし1か所書き換え漏れがあれば LSP が自動で報告し、Claude がその場で直す。読者は「ビルドしてエラーがあったら教えて」と言う必要がない。
シナリオ2: Python の家計簿スクリプトを Rust に書き直してもらう
個人開発の Python 家計簿スクリプト 200行を、Rust の小さなコマンドに移植したい。Rust 側は rust-analyzer という language server が非常に成熟しているため、Claude が型を厳密に詰めながら書き進めても、各編集後に LSP がエラーを拾ってくれる。所有権周りの間違いも書いた瞬間に気付く。逆にこの作業で plugin を入れずに進めると、Claude は「正しいと思いますが手元で動かしてください」と言うしかなく、読者側の確認往復がやたら増えます。
シナリオ3: 数百ファイルある OSS を読み解いて、ある関数の影響範囲を知りたい
仕事で OSS の中身を把握する必要があり、parseRequest という関数が「結局どこからどこまで影響しているか」を知りたい場面。Claude に「parseRequest の call hierarchy を3階層辿って、最終的にどんな外部呼び出しに繋がるか整理して」と頼むと、LSP の呼び出し階層追跡で機械的に辿ってくれます。Grep で文字列検索だと「同名の別関数」「テストの mock」が混ざるので、ノイズが多くて使い物になりません。LSP はそこを正確に分離してくれる。
初心者が踏みやすい落とし穴
- plugin を入れていないと完全に黙ったまま。エラーも警告も出ません。「Claude が型を見てくれない」と感じたら、まず該当言語の code intelligence plugin が入っているかを
/pluginで確認します - plugin を入れただけで language server 本体を入れ忘れる。plugin は「設定」を運んでくるだけで、実体である
typescript-language-serverなどは別途インストールが必要。「plugin 入れたのに静かなまま」のときはこれを疑う - 権限ルールの名前が LSP ではなく Read 系。公式の取り決めは
Read(~/secrets/**)という形で書きます。これは Read・Grep・Glob・LSP の4つに同時に効く場所書きルール。LSP(...)という書き方は存在しません。~/secrets/**を読ませたくない時は Read 側のルールで止める - 権限承認は要らない。公式の Permission Required は No です。設定で禁止していない限り、Claude は確認なしに型情報や参照を引きにいきます。秘密の場所を見られたくない時は、Read のルールで明示的に止める必要があります
- LSP は実行系ではない。テストを走らせたり本物のビルドを通したりはしません。「型としては合っているが実行時には壊れる」コードを出されることがあるので、最終確認は Bash でテストやビルドを走らせて担保する
- language server が古いと結果が嘘になる。version が古いと最新の言語仕様についてこれず、「正しいコードなのに型エラーと言われる」「誤った型情報が返る」が起きます。language server 本体は定期的に更新する
- Grep / Glob と役割が違う。文字列の検索なら Grep が速い。symbol 単位で構造的に追いたい時に LSP を使う。両者を使い分けないと、Claude にとっても遠回りな読み方になります
書き方
LSP は道具なので、人が叩くコマンドではない。Claude が裏で自動的に呼ぶ。読者側がやることは、該当言語の code intelligence plugin を入れて、その plugin が要求する language server 本体を別途インストールしておくだけ。
権限を絞りたい場合のルールの書き方:
Read(~/secrets/**) # この場所書きルールが Read / Grep / Glob / LSP の4つに同時に効く
権限承認は不要(Permission Required: No)
やってみるとこうなる
入力
(読者が直接 LSP を呼ぶことはない)
Claude への依頼例:
「SearchBar の props を { query: string } から { query: string; category?: string } に広げて、カテゴリ絞り込み機能を追加してほしい」
この依頼を受けた Claude は、裏で LSP に向かって順に以下を呼ぶ:
- Jump to a symbol's definition(SearchBar の定義位置)
- Find all references to a symbol(SearchBar を呼んでいる箇所一覧)
- Get type information at a position(searchRecipes の現在の型)
- Find implementations of an interface(必要に応じて)
出力例
Claude が編集した直後、LSP は自動的に型エラー報告を Claude に返す:
src/pages/search.tsx:24 type error:
Property 'category' does not exist on type '{ query: string }'
src/components/Header.tsx:48 warning:
Unused import 'CategoryIcon'
Claude はこれを受け取って、その場で書き換え漏れを修正する。読者が `npm run build` を手動で走らせてエラーログを貼り付ける、という往復作業がほぼ消える。
このページに出てきた言葉
- LSP
- Language Server Protocol の略。Claude Code 内蔵の道具の名前でもある。language server とコード補完ツールが会話するための共通ルール
- language server
- プログラミング言語ごとに用意される「文法と構造に詳しい裏方プログラム」。コードを読んで定義位置・参照箇所・型情報を答える役
- code intelligence plugin
- Claude Code に後付けする部品。入れると、その言語向けの language server 設定がまとめて入る。本体の language server プログラムは別途インストールが必要
- symbol
- コードの中の『名前』のこと。変数名・関数名・クラス名・型名などをまとめてこう呼ぶ
- call hierarchy
- ある関数が『誰から呼ばれていて』『誰を呼んでいるか』を樹形図のように辿れる機能。呼び出し関係の地図
- implementation
- interface(仕様の取り決め)に従って実際に動くコードを書いたもの。1つの interface に対して複数の implementation が存在することがある
- props
- React のコンポーネントが外から受け取る入力データ。関数の入力に近い
関連項目
公式ドキュメント
https://code.claude.com/docs/en/tools-reference#lsp-tool-behavior