Claude Codeに、メンテナンスしている JetBrains IDE プラグイン Railroads のソースコードを解説させてみた

最近、JetBrains IDE と Claude Code が統合できるようになりました。
IDE統合 - Anthropic

JetBrains IDEマーケットプレイスでも、 Claude Code と統合する Anthropic 製プラグインが公開されています。
Claude Code [Beta] Plugin for JetBrains IDEs | JetBrains Marketplace

これらの内容が気になるので、 Cluade Max プランを契約して色々試しています。

 
そんな中、Claude Codeを使ってコードを解説させるのが良いという話を見かけました。

 
そういえば、以前、自分がメンテナンスしている JetBrains IDE プラグインの Railroads について、DeepWiki を設定して解説させてみたことがありました。
メンテナンスしている JetBrains IDE プラグインの Railroads に DeepWiki を設定してみた - メモ的な思考的な

DeepWikiのときと同じ質問を Claude Code にするとどのような結果になるか気になったことから、試してみたときのメモを残します。

 
目次

 

環境

  • Claude Code 1.0.9
  • Claude 4 Opus
  • IntelliJ IDEA 2025.1.1.1
  • Claude Code plugin 0.1.6-beta

 

セットアップ

このブログでは Claude Code を使うのは初めてなので、 Claude Code をセットアップしたときの記録も残しておきます。

公式ドキュメントに従ってセットアップします。
Claude Codeを使い始める - Anthropic

Claude Code は、 Node.js 18以降が必要なので、バージョン確認します。

% node -v
v22.14.0

 
Node.jsのバージョンは問題なさそうなので、npmでインストールします。

% npm install -g @anthropic-ai/claude-code

added 3 packages in 4s

2 packages are looking for funding
  run `npm fund` for details
Reshimming mise 22.14.0...

 
claude コマンドで起動します。テーマは 1. Dark mode にします。

╭──────────────────────────╮
│ ✻ Welcome to Claude Code │
╰──────────────────────────╯

 Let's get started.

 Choose the text style that looks best with your terminal:
 To change this later, run /theme

 ❯ 1. Dark mode

 
ログイン方法の質問には、Claude Max プランを使うことを選択します。  

  Claude Code can now be used with your Max subscription from the Claude app or billed based on API usage through your Console
  account.


 Select login method:

 ❯ 1. Claude account with Max subscription
      Starting at $100/mo - Best value, predictable pricing

 
ブラウザでの認証画面が開くので、認証します。認証が終わったところでブラウザを閉じます。

 Browser didn't open? Use the url below to sign in:

https://claude.ai/***

 Logged in as ***


 Login successful. Press Enter to continue…

 
次は Security noteが表示されるので、内容を確認します。

 Security notes:

 1. Claude can make mistakes
    You should always review Claude's responses, especially when
    running code.

 2. Due to prompt injection risks, only use it with code you trust
    For more details see:
    https://docs.anthropic.com/s/claude-code-security

 Press Enter to continue…

 
ターミナルのセットアップは推奨の設定を使用します。

 Use Claude Code's terminal setup?

 For the optimal coding experience, enable the recommended settings
 for your terminal: Option+Enter for newlines and visual bell

 ❯ 1. Yes, use recommended settings

 
railroadsディレクトリについては trust です。

 Do you trust the files in this folder?

  /path/to/railroads

Claude Code may read files in this folder. Reading untrusted files may lead Claude Code to behave in an unexpected ways.

With your permission Claude Code may execute files in this folder. Executing untrusted code is unsafe.

https://docs.anthropic.com/s/claude-code-security

❯ 1. Yes, proceed  

 
設定が終わりました。

╭───────────────────────────────────────────────────╮
│ ✻ Welcome to Claude Code!                         │
│                                                   │
│   /help for help, /status for your current setup  │
│                                                   │
│   cwd: /path/to/railroads          │
╰───────────────────────────────────────────────────╯

 Tips for getting started:

 1. Run /init to create a CLAUDE.md file with instructions for Claude
 2. Use Claude to help with file analysis, editing, bash commands and git
 3. Be as specific as you would with another engineer for the best results
 4. ✔ Run /terminal-setup to set up terminal integration

 ※ Tip: Start with small features or bug fixes, tell Claude to propose a plan, and verify its suggested edits

 
設定が終わったので、 /status でステータスを確認します。

> /status 
  ⎿  (no content)

 Claude Code Status v1.0.9

 Working Directory 
  L /path/to/railroads

 Account • /login
  L Login Method: Claude Max Account
  L Email: ***

 Model • /model
  L Default Use Opus 4 or Sonnet 4 based on Max usage limits (currently Opus)

 

Claude Code による解説 

プラグインの概要について質問

まずは概要について質問してみました。

コードを一通り読んで解説して

 
回答は以下でした。

⏺ このRailroadsプロジェクトのコードを読んで解説します。

⏺ Update Todos
  ⎿  ☐ プロジェクト構造と設定ファイルの確認
     ☐ 主要なモデルクラスの解析
     ☐ パーサーの実装確認
     ☐ UIコンポーネントの確認
     ☐ アクション機能の確認

⏺ Task(プロジェクト設定と構造を確認)…
  ⎿  Done (3 tool uses · 18.3k tokens · 36.8s)

⏺ Update Todos
  ⎿  ☒ プロジェクト構造と設定ファイルの確認
     ☐ 主要なモデルクラスの解析
     ☐ パーサーの実装確認
     ☐ UIコンポーネントの確認
     ☐ アクション機能の確認

⏺ Task(モデルクラスの詳細解析)…
  ⎿  Done (9 tool uses · 20.2k tokens · 1m 47.2s)

⏺ Update Todos
  ⎿  ☒ プロジェクト構造と設定ファイルの確認
     ☒ 主要なモデルクラスの解析
     ☐ パーサーの実装確認
     ☐ UIコンポーネントの確認
     ☐ アクション機能の確認

⏺ Read(src/main/kotlin/com/github/thinkami/railroads/parser/RailsRoutesParser.kt)…
  ⎿  Read 157 lines (ctrl+r to expand)

⏺ Read(src/test/kotlin/com/github/thinkami/railroads/parser/RailsRoutesParserParseTest.kt)…
  ⎿  Read 19 lines (ctrl+r to expand)

⏺ Update Todos
  ⎿  ☒ プロジェクト構造と設定ファイルの確認
     ☒ 主要なモデルクラスの解析
     ☒ パーサーの実装確認
     ☐ UIコンポーネントの確認
     ☐ アクション機能の確認

⏺ Task(UIコンポーネントとアクションを分析)…
  ⎿  Done (13 tool uses · 22.2k tokens · 1m 52.2s)

⏺ Update Todos
  ⎿  ☒ プロジェクト構造と設定ファイルの確認
     ☒ 主要なモデルクラスの解析
     ☒ パーサーの実装確認
     ☒ UIコンポーネントの確認
     ☒ アクション機能の確認

⏺ Railroadsプロジェクトの総合解説

  プロジェクト概要

  RailroadsはIntelliJ IDEA/RubyMine用のプラグインで、Rails アプリケーションのルーティング情報を視覚的に表示し、コントローラー/アクションへのナビゲーションを提供します。

  アーキテクチャの特徴

  1. 階層的なルートモデル設計
  - BaseRouteを基底クラスとして、3種類のルート(SimpleRoute、RedirectRoute、MountedEngineRoute)を実装
  - IntelliJのNavigationItem インターフェースを実装し、コードナビゲーションをサポート

  2. パーサーの実装
  - RailsRoutesParserが「rails routes」コマンドの出力を解析
  - 正規表現を使用した効率的なパース処理
  - マウントされたエンジンルートへの対応

  3. UIアーキテクチャ
  - ToolWindow ファクトリーパターンによる統合
  - MVCパターンに基づくテーブルモデル実装
  - 状態管理を明確に分離(デフォルト、ローディング、エラー、ルート表示)

  4. アクションシステム
  - IntelliJのアクションシステムと統合
  - コンテキストメニューによるルート情報のコピー機能
  - バックグラウンドスレッドでの処理実行

  主要な機能

  1. ルート表示: Railsアプリケーションの全ルートをテーブル形式で表示
  2. フィルタリング: ワイルドカード対応のリアルタイムフィルタリング
  3. コードナビゲーション: ルートからコントローラー/アクションへの直接ジャンプ
  4. コンテキストメニュー: ルート名、パス、フルパスのコピー機能
  5. エンジン対応: マウントされたRailsエンジンのルート表示

  技術的な優れた点

  - Kotlin言語の活用: データクラス、拡張関数、null安全性
  - IntelliJプラットフォーム統合: PSI、タスク、通知システムの適切な使用
  - テスト可能性: モックフレームワークを使用した単体テスト
  - 拡張性: 新しいルートタイプやフィルタリング条件の追加が容易

  このプラグインは、優れたオブジェクト指向設計とIntelliJプラットフォームの機能を最大限に活用し、Rails開発者の生産性向上に貢献する実用的なツールとなっています。

 

リポジトリの実装に関する質問

続いて、DeepWikiとの差を確認するため、同じプロンプトで Claude Code に質問してみました(以降の質問も同様です)。

railroadsでrails routesコマンドの結果はどうやって取得しているのか、解説してください

 
回答は以下でした。DeepWikiと比べると 通知バルーン の解説が見当たりませんでしたが、概ね良さそうです。該当のソースコードを引用して解説するのも同じような感じでした。

⏺ rails routesコマンドの実行と結果取得の仕組みを詳しく解説します。

⏺ Read(src/main/kotlin/com/github/thinkami/railroads/models/tasks/RoutesTask.kt)…
  ⎿  Read 102 lines (ctrl+r to expand)

⏺ Search(pattern: "RubyGemExecutionContext", include: "*.kt")…
  ⎿  Found 1 file (ctrl+r to expand)

⏺ Read(src/main/kotlin/com/github/thinkami/railroads/actions/RailsRouteAction.kt)…
  ⎿  Read 19 lines (ctrl+r to expand)

⏺ Rails Routesコマンドの実行と結果取得の仕組み

  Railroadsプラグインでは、以下の流れでrails routesコマンドを実行し、結果を取得しています:

  1. 実行の起点

  - ユーザーが「Rails Routes」ボタンをクリック
  - RailsRouteActionがRoutesTaskを作成し、バックグラウンドタスクとしてキューに追加

  2. RoutesTaskの実行プロセス

  事前チェック (RoutesTask.kt:25-46)

  // Railsアプリケーションの検証
  val app = RailsApp.fromModule(module)
  if ((app == null) || (app.railsApplicationRoot == null)) {
      mainView.renderDefaultWithUiThread()
      return
  }

  // Ruby SDKの存在確認
  val manager = ModuleRootManager.getInstance(module)
  if (manager.sdk == null) {
      mainView.renderDefaultWithUiThread()
      return
  }

  コマンド実行 (RoutesTask.kt:51-56)

  val result = RubyGemExecutionContext.create(sdk, "rails")
      .withModule(module)
      .withWorkingDirPath(moduleContentRoot)
      .withExecutionMode(ExecutionModes.SameThreadMode())
      .withArguments("routes", "--trace")
      .executeScript()

  3. 実行の詳細

  RubyGemExecutionContextの役割:
  - IntelliJ/RubyMineのRubyプラグインが提供するAPI
  - Ruby SDKを使用してGemコマンドを実行
  - プロセスの標準出力とエラー出力をProcessOutputとして返す

  実行パラメータ:
  - gem: "rails"
  - 引数: "routes", "--trace"
  - 作業ディレクトリ: Railsアプリケーションのルート
  - 実行モード: SameThreadMode(同期実行)

  4. 結果の処理 (RoutesTask.kt:66-96)

  エラーハンドリング:

  if (output.stdout.isBlank() && output.stderr.isNotBlank()) {
      // エラー通知を表示
      val notification = Notification(
          "railroadsNotification",
          "Railroads Error: fail rails routes",
          output.stderr,
          NotificationType.ERROR
      )
      Notifications.Bus.notify(notification)
      MainView(toolWindow).renderErrorWithUiThread()
      return
  }

  正常時の処理:

  // 標準出力をパースしてルート情報を抽出
  val routes = RailsRoutesParser(module).parse(output.stdout)
  // UIにルート情報を表示
  MainView(toolWindow).renderRoutesWithUiThread(routes)

  5. 実行環境の特徴

  1. バックグラウンド実行
    - Task.Backgroundableを継承し、UIをブロックしない
    - プログレスインジケーターで進捗を表示
  2. IDEとの統合
    - プロジェクトのRuby SDKを自動的に使用
    - Railsアプリケーションのルートディレクトリを自動検出
  3. エラー処理
    - 標準エラー出力をチェックし、適切にエラー表示
    - 警告(deprecationなど)は無視(stdout + stderrの場合)
  4. 同期実行
    - SameThreadModeにより、コマンドの完了を待機
    - 結果を確実に取得してからパース処理を実行

  この実装により、Railsプロジェクトの実際のrails routesコマンドを実行し、その出力を取得して解析することで、常に最新のルーティング情報を表示できるようになっています。

 

Railroads 実装範囲外の質問

続いて、Railroadsの実装範囲外の機能についても質問してみました。

RubyGemExecutionContextとはなんですか

 
回答はこちらです。DeepWikiと同じように、 RubyGemExecutionContext の説明に加え、Railroadsではどのように使っているかの回答をもらいました。

⏺ RubyGemExecutionContextは、IntelliJ IDEA/RubyMineのRubyプラグインが提供する、RubyやGemコマンドを実行するためのAPIです。詳しく解説します。

⏺ Search(pattern: "RubyGemExecutionContext|executeScript|ExecutionModes", include: "*.kt")…
  ⎿  Found 1 file (ctrl+r to expand)

⏺ RubyGemExecutionContextの詳細解説

  概要

  RubyGemExecutionContextは、JetBrains RubyプラグインのAPIで、Ruby環境でGemコマンドやRubyスクリプトを実行するためのコンテキストを提供します。

  RoutesTask.ktでの使用例

  val result = RubyGemExecutionContext.create(sdk, "rails")
      .withModule(module)
      .withWorkingDirPath(moduleContentRoot)
      .withExecutionMode(ExecutionModes.SameThreadMode())
      .withArguments("routes", "--trace")
      .executeScript()

  主要な機能と設定

  1. コンテキストの作成

  RubyGemExecutionContext.create(sdk, "rails")
  - sdk: Ruby SDKインスタンス(プロジェクトで設定されたRubyバージョン)
  - "rails": 実行するGemの名前

  2. 実行環境の設定

  モジュール設定
  .withModule(module)
  - IntelliJのモジュールコンテキストを指定
  - Bundlerなどのプロジェクト固有の設定を反映

  作業ディレクトリ
  .withWorkingDirPath(moduleContentRoot)
  - コマンドを実行する作業ディレクトリ
  - 通常はRailsアプリケーションのルートディレクトリ

  実行モード
  .withExecutionMode(ExecutionModes.SameThreadMode())
  - SameThreadMode(): 同期実行(現在のスレッドで実行し、完了を待つ)
  - 他のモード:非同期実行、デバッグモードなど

  コマンドライン引数
  .withArguments("routes", "--trace")
  - Gemに渡す引数
  - この例では rails routes --trace を実行

  実行結果の取得

  val result = /* ... */.executeScript()
  if (result != null) {
      output = result  // ProcessOutput型
  }

  ProcessOutputには以下が含まれます:
  - stdout: 標準出力
  - stderr: 標準エラー出力
  - exitCode: 終了コード

  RubyGemExecutionContextの利点

  1. IDE統合
    - プロジェクトのRuby SDK設定を自動的に使用
    - Bundler環境を考慮した実行
  2. プラットフォーム非依存
    - Windows、macOS、Linuxで同じコードが動作
    - パスやコマンドの違いを吸収
  3. エラーハンドリング
    - 実行結果をProcessOutputとして構造化
    - 標準出力とエラー出力を分離
  4. プロジェクト設定の反映
    - .ruby-version、Gemfileなどの設定を考慮
    - RVM、rbenvなどのRubyバージョン管理ツールに対応

  実際の動作フロー

  1. 準備段階
    - Ruby SDKのパスを解決
    - Bundlerがある場合はbundle execを付与
    - 環境変数を設定
  2. 実行段階
    - 実際のコマンド例:/path/to/ruby /path/to/bundle exec rails routes --trace
    - 作業ディレクトリで実行
    - 出力をキャプチャ
  3. 結果返却
    - ProcessOutputオブジェクトとして返却
    - 呼び出し元で出力を解析

  まとめ

  RubyGemExecutionContextは、IntelliJ/RubyMineがRubyコマンドを実行する際の複雑さを隠蔽し、簡潔なAPIで外部コマンドを実行できるようにする重要なコンポーネントです。Railroadsプラグインはこれを使用し
  て、rails routesコマンドを確実に実行し、その結果を取得しています。

 

PSIの利用箇所に関する質問

最後に、PSIの利用について質問しました。

railroadsはprogram structures interface を使っていますか?

 
DeepWikiの場合は DeepResearch を使わないと正解を返してこなかったのですが、 Claude Code はデフォルトで Claude 4 Opus を使っているせいか、「使っている」という正しい回答を返してきました。

また、DeepWikiでは英語での返答でしたが、 Claude Code は日本語になっていました。

⏺ はい、RailroadsプラグインはProgram Structure Interface (PSI)を積極的に使用しています。以下、具体的な使用箇所を解説します。

⏺ Search(pattern: "Psi", include: "*.kt")…
  ⎿  Found 4 files (ctrl+r to expand)

⏺ Read(src/main/kotlin/com/github/thinkami/railroads/helper/PsiUtil.kt)…
  ⎿  Read 125 lines (ctrl+r to expand)

⏺ Read(src/main/kotlin/com/github/thinkami/railroads/models/RailsAction.kt)…
  ⎿  Read 66 lines (ctrl+r to expand)

⏺ Search(pattern: "navigate|canNavigate|NavigationItem", include: "*.kt")…
  ⎿  Found 5 files (ctrl+r to expand)

⏺ RailroadsプラグインのPSI使用状況

  はい、RailroadsプラグインはIntelliJのProgram Structure Interface (PSI)を広範囲に使用しています。主な使用箇所と目的を解説します:

  1. PSI要素の管理と参照

  PsiUtil.kt - PSIユーティリティクラス

  // PSI要素の検索と取得
  fun findControllerClass(app: RailsApp, qualifiedClassName: String): RClass? {
      // RailsアプリケーションからコントローラーのPSIクラスを検索
      val controller = app.findController(qualifiedClassName)
      if (controller != null) {
          return controller.rClass  // RClass = Ruby PSIクラス要素
      }
      // StubIndexを使用してクラスを検索
      val container = findClassOrModule(qualifiedClassName, app.project)
      return if (container is RClass) container else null
  }

  主要なPSI要素:
  - RClass - Rubyクラスの PSI表現
  - RModule - Rubyモジュールの PSI表現
  - RMethod - Rubyメソッドの PSI表現
  - RCall - Rubyメソッド呼び出しの PSI表現

  2. コードナビゲーション機能

  BaseRoute.kt - NavigationItemインターフェースの実装

  abstract class BaseRoute(
      val module: Module,
      val requestMethod: String,
      val routePath: String,
      val routeName: String,
      val controllerName: String,
      val actionName: String
  ) : NavigationItem  // IntelliJのナビゲーションインターフェース

  SimpleRoute.kt - 実際のナビゲーション実装

  override fun navigate(requestFocus: Boolean) {
      railsAction.update(module, controllerName, actionName)

      if (railsAction.psiMethod != null && railsAction.psiMethod!!.isValid) {
          // メソッドのPSI要素に直接ナビゲート
          railsAction.psiMethod!!.navigate(requestFocus)
      } else if (railsAction.psiClass != null && railsAction.psiClass!!.isValid) {
          // クラスのPSI要素にフォールバック
          railsAction.psiClass!!.navigate(requestFocus)
      }
  }

  3. PSI要素の有効性チェック

  RailsAction.kt - PSI要素のライフサイクル管理

  fun update(app: RailsApp?, controllerShortName: String, actionName: String) {
      // PSI要素の有効性をチェック
      if (psiClass != null && (!psiClass!!.isValid || psiClass!!.fqn.fullPath != qualifiedName)) {
          psiClass = null
          psiMethod = null
      }

      // 無効になった場合は再取得
      if (psiMethod == null || !psiMethod!!.isValid) {
          psiMethod = PsiUtil.findControllerMethod(app, psiClass!!, actionName)
      }
  }

  4. StubIndexの活用

  PsiUtil.kt - 高速な要素検索

  private fun findClassesAndModules(name: String, project: Project): Collection<RElementWithFQN> {
      val scope = RubyProjectAndLibrariesScope(project)
      // StubIndexを使用して効率的にクラス/モジュールを検索
      return StubIndex.getElements(
          RubyClassModuleNameIndex.KEY,
          name,
          project,
          scope,
          RElementWithFQN::class.java
      )
  }

  5. PSI Tree の走査

  PsiUtil.kt - includeされたモジュールの検索

  private fun findMethodInClassModules(controllerClass: RClass, methodName: String): RMethod? {
      // PSI Treeを走査してinclude文を収集
      val elements = PsiTreeUtil.collectElements(controllerClass, INCLUDE_MODULE_FILTER)

      // 各include文からモジュールを解決してメソッドを検索
      for (includeMethodCall in elements) {
          val moduleNameArg = includeMethodCall.arguments[0]
          val container = findClassOrModule(moduleNameArg.text, controllerClass.project)
          // モジュール内のメソッドを検索
      }
  }

  6. ReadActionによる安全なPSI読み取り

  RailsAction.kt - スレッドセーフなPSI読み取り

  fun getIcon(): Icon = ReadAction.compute<Icon, Throwable> {
      // ReadAction内でPSI要素にアクセス
      val visibility = psiMethod?.visibility
      when (visibility) {
          Visibility.PRIVATE, Visibility.PROTECTED -> RailroadIcon.NodeMethod
          Visibility.PUBLIC -> RailroadIcon.NodeRouteAction
          else -> RailroadIcon.Unknown
      }
  }

  PSI使用の主な目的

  1. コードナビゲーション: ルートから対応するコントローラー/アクションへジャンプ
  2. メソッド存在確認: アクションメソッドが実装されているかチェック
  3. アイコン表示: メソッドの可視性に基づいて適切なアイコンを表示
  4. Ruby固有の機能: includeされたモジュール、継承階層の解析
  5. 高速検索: StubIndexを使用した効率的なクラス/モジュール検索

  このように、RailroadsプラグインはPSIを活用することで、単なるテキスト解析を超えた、IDEと深く統合されたナビゲーション機能を提供しています。

 

おわりに

Railroads プラグインについて、Claude Code 1.09 と 2025/04/30 時点の DeepWIki とで回答を比較してみました。

両者をそこまで使い込んでいない状態ではありますが、今回使った範囲では大きな差は感じませんでした。

引き続き Claude Code を使ってみて、何か気づいたことがあれば追記などしていきたいと思います。