何をしたいか
NDF を入れた Claude Code と Codex で .py / .php / .ts(.js)を扱うとき、定義・参照・診断(型エラー・未解決の import)と、コードを読む量を抑えた編集ができるようにする。
方針(実測にもとづく結論)
ランタイム
診断
シンボルの把握・参照・編集
Claude Code
plugin LSP servers
Serena
Codex
Serena
Serena
役割を分け、同じ言語で機能を重複させない。Serena 側の #858 も、重複したツールが並ぶとコンテキストの無駄になると指摘している。
具体例
plugins/ndf/scripts/lib/monitor.py(1,247 行)の _safe_size を、例外のときに 0 ではなく -1 を返すよう変え、呼び出し側への影響を調べる。今は Read でファイル全体(48,847 文字)が入り、型の食い違いは pytest を流すまで分からない。
調べて分かったこと
1. Serena はほぼ使われていない(手元のセッション記録で実測)
2026-06-24〜09-22 のセッション記録から、tool_use を集計した。
ランタイム
記録数
Serena の呼び出し
参考
Claude Code(サブエージェントを含む)
約 7,500 ファイル
10 回(4 セッション) 。replace_in_files 3 / initial_instructions 3 / get_symbols_overview 2 / activate_project 1
Bash 98,660 / Read 8,262 / Edit 8,523 / Grep 173
Codex
約 4,000 ファイル
0 回 。ただし codex plugin list で mcp-serena@ai-plugins は not installed だった。使われなかったのではなく、入っていなかった
bigquery 100 / dbhub 96
本来の用途である find_symbol / find_referencing_symbols は一度も呼ばれていない。
2. なぜ使われなかったか
呼んだ 10 回のうち 7 回が失敗していた。 作業として成功したのは Markdown の文字列置換 1 回だけで、sed でも済む作業だった。
日時・場所
呼び出し
結果
06-27 carmo-predict-contract(サブエージェント)
get_symbols_overview ×2
No active project で失敗し、以後は呼ばれなかった
08-07 ai-plugins
replace_in_files → activate_project → replace_in_files ×2
1 回目は No active project、2 回目は expected_count の食い違いで失敗し、3 回目で成功
08-13 検証用リポジトリ
initial_instructions ×3
権限が許可されず、最後は拒否
原因は 4 つある。いずれも配布設定の不備で、モデルの性質ではない。
言語の設定が、実際のコードと合っていない。 /work/ai-plugins/.serena/project.yml の language_servers は - bash だけで、このリポジトリの .py 322 個(約 9 万行)にシンボル機能が効かない。手元の /work/*/.serena/project.yml 9 個のうち、言語を設定しているのは 3 個だけだった
使い始めるまでの段階が多い。 ツールは遅延読み込みで ToolSearch が要り、activate_project が要り(--project-from-cwd が無いため)、Serena 自身が先に initial_instructions を読むよう求める
指示の中での扱いが弱い。 CLAUDE.md やエージェント定義には「Serena を活用」とあるだけで、どの場面で grep ではなく Serena を使うかが書かれていない。qa.md のツール名は古い名前空間 mcp__plugin_ndf_serena__* のままで、今のツールに届かない
Serena に触れているエージェント(corder など)が呼ばれる回数も少ない
3. 読み込む量の実測(Claude Code、sonnet-5、同じタスクを 5 条件)
題材は monitor.py(1,247 行)の _safe_size の変更と、呼び出し側への影響の報告。
条件
使われたツール
ツール結果の文字数
最終手番のコンテキスト
A 素の状態
Read(全体)→ Edit
51,631
68,532
B LSP あり・指示なし
Read(全体)→ Edit
49,057
66,094
C Serena あり・指示なし
Read(全体)→ Edit
49,467
66,985
D Serena あり・使うよう指示
find_symbol / find_referencing_symbols / replace_symbol_body
18,577
51,355
E LSP あり・使うよう指示
LSP(documentSymbol / findReferences)+ 範囲を絞った Read 4 回
13,517
49,466
指示しなければ、どちらも使われずファイル全体が読まれる。 差を決めているのは機能ではなく誘導である
起動時の約 39.5k トークンを除いた増分で比べると、素の状態 29k に対し D は 11.4k、E は 10k。Serena と LSP の節約量はほぼ同じ
D の読み込みの半分(9,208 文字)は initial_instructions だった。これを外せば Serena が有利になる
Serena を載せても初回のコンテキストはほとんど増えない (D 39,925 / E 39,480 トークン)。ツールが遅延読み込みのため、併用のコストは小さい
4. Claude Code の plugin LSP servers(実測)
--plugin-dir で LSP 定義だけのプラグインを読み込ませて確認した。
編集後の診断は自動で届く。 次の手番の system-reminder に <new-diagnostics> として入る(Python の reportOperatorIssue、TypeScript の 2362 を確認)
届くのは編集したファイルの分だけ。 util.py の型を変えて壊れた呼び出し側 a.py の分は届かなかった
呼べる操作は 9 種類(goToDefinition / findReferences / hover / documentSymbol / workspaceSymbol / goToImplementation / prepareCallHierarchy / incomingCalls / outgoingCalls)。診断を取る操作も rename も無い
LSP ツールも遅延読み込みで、ToolSearch を 1 回挟む
言語サーバ本体は利用者が入れる。同じ拡張子を複数のプラグインが宣言すると、最初に登録されたものだけが動く
言語サーバ本体が無くても、セッション中には何も表示されない。 実在しないコマンドを lspServers に宣言したプラグインで .rb を編集したが、警告もエラーも届かず、診断が来ないだけだった。「動いているつもりで動いていない」状態に気付けない ため、検査は自前で持つ必要がある
公式の typescript-lsp は、案内どおりに入れると動かない。 npm install -g typescript で入る latest は 7.0.2 (Go への移植版)で tsserver.js を持たないため、typescript-language-server が初期化に失敗する。しかも失敗は表示されず、診断が届かないだけになる。typescript@5 に固定すると動いた(Serena は ^5.9.3 を自分で入れるため、この問題を踏まない)
5. Codex には LSP の仕組みが無い(実測)
codex --version は 0.154.0。codex features list にも設定キーにも lsp 系が無い。Codex で LSP を使うには MCP でつなぐしかない。
Codex の利用上限のため Codex からは試せず、代わりに MCP クライアントから Serena を直接呼んで確かめた(--context codex --project-from-cwd)。
言語
言語サーバ(Serena が自分で入れる)
find_referencing_symbols
get_diagnostics_for_file
Python
pyright
通った
reportArgumentType を返した
TypeScript
typescript-language-server
通った
2345 を返した
PHP
intelephense
通った
空 (無料版は型の食い違いを診断しないと見ている。要確認)
--project-from-cwd を付けると、activate_project を呼ばずに最初の呼び出しから通る。 ただし、この版ではツール一覧から activate_project が消えはしなかった
言語サーバ本体を利用者が入れなくてよい (~/.serena/language_servers/static/ へ Serena が入れる)
自動で入れた言語サーバのキャッシュが壊れることがある。手元では TypeScript のものが ENOENT ... node_modules/package.json で初期化に失敗した(symlink が実体のコピーになっていた)。退避して入れ直させると動いた
6. Serena 以外の LSP-MCP は、配って使うには弱い
候補
★
最近の更新
1 つのサーバで扱える言語
言語サーバ本体
oraios/serena
29,715
毎日。正式版 v1.7.0(2026-08)
複数
自動で入る
isaacphi/mcp-language-server
1,596
実質 2025-05 で停止
1 言語 (--workspace の絶対パスも要る)
利用者が入れる
ktnyt/cclsp
676
2026-02 が最後
複数
利用者が入れる
jonrad/lsp-mcp、Tritlo/lsp-mcp
191 / 124
2025 で停止
—
利用者が入れる
7. 公式の hook で「使わせる」仕組みがある(外部調査)
Serena には公式の hook(serena-hooks)がある。
PreToolUse で grep や Read が続くと permissionDecision: "deny" を返して Serena の使用を促し、直後にカウンタを戻すため作業は止まらない(閾値は grep 3 回 / コードファイルの Read 3 回 / 混在 4 回、120 秒のクールダウン)
SessionStart の activate、Serena ツールの auto-approve、SessionEnd の cleanup もある
公式サンプルの matcher mcp__serena__* は、私たちの配布名 mcp__plugin_mcp-serena_serena__* に一致しない。 書き換えが要る
serena-hooks を uvx で毎回起動すると、ツール呼び出しのたびに遅延が乗る。プラグインに実装を同梱するか、導入時に uv tool install serena-agent を求めるかを決める(未計測)
公式ドキュメントは、Claude Code の組み込みツールの説明が強いバイアスになると認めており、serena prompts print-cc-system-prompt-override と hook を勧めている
Serena 本体を Skill にする案は、上流が #802 で否定している(言語サーバを毎回起動することになるため)。私たちが作るのは「Serena を呼ばせる薄い Skill / hook」である
出典: Connecting Your MCP Client / #802 / #858 / plugins reference
8. プロジェクトに依存しない設計にするための実測
このリポジトリ専用の設定にしない。言語は導入先ごとに違うため、検出して設定する 形にする。
Serena は約 45 言語に対応している (solidlsp/ls_config.py の Language。python / typescript / php / go / ruby / java / rust / csharp / kotlin / swift / bash / terraform / vue / svelte など)。拡張子との対応も Serena 自身が持つ(Language.get_source_fn_matcher)
serena project create の言語推定は、最も多い言語だけを自動で選び、残りは対話で確認する。 複数言語のリポジトリで試すと Enable typescript (28.57% of source files)? [y/N] と聞かれ、非対話では Error: EOF when reading a line で失敗した。ai-plugins が bash だけになっているのは、この経路を通ったためと見られる
非対話の手段はある。 serena project create --ls python --ls typescript ... のように --language を複数回渡せる
単一言語のリポジトリでは、自動生成された project.yml は正しく検出していた(python / typescript / php のプローブで確認)
検出は作成時の 1 回だけで、以後は更新されない。 言語が増えたリポジトリでは設定が古いまま残る
不要な言語を足したときの代償(混在リポジトリで実測。Python 3 / TypeScript 2 / PHP 1 / bash 1 ファイル)
python のみ
python + typescript + php + bash
初回の find_symbol
0.1 秒
4.2 秒
メモリ(既存プロセス 345MB を差し引いた分)
約 344MB
約 880MB (2.5 倍)
initialize
1.9 秒
1.7 秒(差は無い)
いちばん大きいのは、1 つの失敗が全体を止めることである。 4 言語で試した 1 回目、bash の言語サーバが壊れていた(Cannot find module './server')ため、Python の find_symbol まで The language server manager is not initialized で失敗した。Serena は Failed to start 1 language server(s) で初期化ごと失敗させる。つまり使っていない言語を足すほど、使っている言語の機能が道連れで止まる確率が上がる 。手元では TypeScript と bash の 2 つでキャッシュ破損が起きていた。
ディスクも増える(intelephense 162MB、bash 48MB、TypeScript 26MB。初回は自動ダウンロードの待ちも入る)。
9. プロジェクトに依存しない仕様(提案)
言語ごとに変わるのは対応表だけ にし、手順と hook は言語に依存させない。
(1) 言語の決め方(共通)
git ls-files の拡張子を数える(追跡対象だけを見る。生成物や node_modules を拾わないため)
件数の多い順に、対応表で言語へ変換する。しきい値(例: 10 ファイル以上、または全体の 5% 以上)を超えたものだけを採る。しきい値を置くのは、上の代償(メモリ 2.5 倍、初回 42 倍、道連れの失敗)を避けるためである
確認は取らずに書く (serena project create --ls <言語> ...)
書いたあと、1 言語ずつ起動を検証し、失敗した言語は設定から外す。 Serena は 1 つの失敗で全シンボル操作を止めるため、これが確認より効く
足した言語、外した言語とその理由を報告する
(2) 成果物は 3 つ
成果物
役割
言語への依存
Skill(導入・検査)
検出 → 確認 → project.yml の生成 → 必要な言語サーバの案内 → 動作確認
対応表のみ
hook(SessionStart)
検出結果と project.yml の食い違い、未導入の言語サーバを知らせる
対応表のみ
hook(PreToolUse)
grep や Read が続いたときにシンボル単位の手順へ誘導する
無し (拡張子の一覧は設定で持つ)
対応表は 1 箇所に置く(例: plugins/ndf/.../languages.json)。拡張子 → Serena の言語識別子 → 公式 LSP プラグイン名 → 言語サーバ本体の導入コマンド、の 4 列
SessionStart の通知は、食い違いがあるときだけ 出す。毎回出すと今の echo と同じく読み飛ばされる
(3) Claude Code の LSP は、NDF に定義を持たせない
導入先の言語は分からないため、lspServers を NDF が固定で持つと、使わない言語の定義が全員に載る。代わりに Skill が検出結果に応じて公式プラグイン(pyright-lsp / typescript-lsp / php-lsp / gopls-lsp / ruby-lsp など)の導入を案内する 。4 で分かったとおり、本体が無くても何も表示されないため、Skill 側で導入の有無を検査する 。
(4) 導入先のリポジトリを汚さない
.serena/project.yml は導入先に作られる。.gitignore へ入れるか、追跡するかは導入先の判断 とし、Skill は選ばせる(このリポジトリでは serena_config.yml に auth_secret が入る問題がある)
作業ツリー(.worktrees/<ブランチ名>)でも動くこと。--project-from-cwd は最も近い境界を選ぶため、作業ツリー側が有効化される
読み取り専用で始められること。検出だけを実行し、設定を書く前に必ず確認を取る
10. ツール名の長さと、起動の仕方(実測)
ツール名は mcp__plugin_<プラグイン名>_<サーバ名>__<ツール名> である。 小さな MCP サーバを作り、名前を変えて確かめた。
プラグイン名
.mcp.json のサーバ名
実際のツール名
mcp-serena
serena
mcp__plugin_mcp-serena_serena__ping(接頭辞 30 文字)
zq
zs
mcp__plugin_zq_zs__ping(接頭辞 18 文字)
zq-long-plugin-name
serena-server-name
mcp__plugin_zq-long-plugin-name_serena-server-name__ping
両方とも私たちが決められる。 ただし mcp__plugin_ の部分は固定で、プラグインとして配る限り公式 hook の matcher mcp__serena__* には一致しない
mcp__serena__* にしたいなら、プラグインではなく利用者の MCP 設定(claude mcp add serena ...)として入れることになる。その場合、プラグインの導入・更新の仕組みから外れる
プラグイン名は導入済みのプラグインと衝突する。 検証中、serena と ndf という名前のプラグインを読み込ませたところ、同名の導入済みプラグインがあるため failed になった。公式マーケットプレイスには Oraios 製の serena プラグインがあるため、私たちのプラグインを serena に改名するのは避ける
${CLAUDE_PLUGIN_ROOT} は .mcp.json で展開され、ラッパースクリプトを起動できる (実測)。したがって「導入済みの Serena があればそれを使い、無ければ uvx」は実現できる。
#! /usr/bin/env bash
# 例: 導入済みを優先し、無ければ uvx で起動する
if command -v serena > /dev/null 2>&1 && serena --version | grep -q " Serena 1\." ; then
exec serena start-mcp-server " $@ "
fi
exec uvx --from serena-agent==1.7.0 serena start-mcp-server " $@ "
版の確認を入れるのは、導入済みが 2.0 系だと破壊的変更(initial_instructions の要求)を踏むためである
uvx の 2 回目以降の起動は 0.8 秒だった (PyPI の serena-agent==1.7.0。git+... は 1.3 秒)。速度のために自動インストールする理由は無い。効くのは初回のダウンロードとオフラインのとき
セッション開始時に黙って uv tool install を走らせるのは避ける。 利用者の ~/.local へ書き込み、ネットワークに依存し、失敗しても気付きにくい。導入は Skill の手順(明示的な実行)と、コンテナ側(devbasex/devbase#236 )で先に入れておく形にする
11. 公式マーケットプレイスの serena プラグインを使わない理由(実物を確認)
claude-plugins-official の serena(Oraios 製、community-managed)の実体は anthropics/claude-plugins-public の external_plugins/serena にあり、中身は .mcp.json 1 つだけである。
{"serena" : {"command" : " uvx" ,
"args" : [" --from" , " git+https://github.com/oraios/serena" , " serena" , " start-mcp-server" ]}}
.claude-plugin/plugin.json は名前と説明のみで、hook は無い。2025-12-02 以降、更新されていない。
論点
公式版
私たちが直す案
版の固定
無し (git+... の main を追う=現在 2.0.0.dev0)。initial_instructions を要求される破壊的変更を踏む
serena-agent==1.7.0 に固定
--project-from-cwd
無し。毎回 activate_project が要る(2 の失敗 3 回の原因)
付ける
--context
無し(既定は desktop-app で、Claude Code 向けのツール除外が効かない)
ランタイム別に指定
memory / onboarding の抑止
無し
no-memories / no-onboarding
hook(誘導・自動許可)
無し
付ける
導入済み Serena の利用
無し
ラッパースクリプトで対応
Codex / Kiro
使えない (Claude Code 専用)
同じ定義を 3 ランタイムへ配れる
公式版は起動引数を変えられないため、hook や Skill を足しても activate_project と開発版の問題が残る。 Codex には、そもそも使えない。よって mcp-serena を維持し、A・B で直す。
併存のリスク(推測) : 私たちの mcp-serena と公式の serena は名前が違うため、両方入れると Serena が 2 つ起動し、ツールが重複してメモリも 2 倍になると見ている(実測したのは同名プラグインどうしの衝突までで、この併存は未確認)。どちらか一方を選ぶよう案内に書く。
上流が起動引数を持つようになったら、乗り換えを再検討する。
12. Bash の扱い(2026-09-23 追記)
量: 追跡対象の .sh は 71 個・14,499 行(.py は 325 個・92,101 行)。hook と plugins/ndf/scripts に多い。今後のスクリプト化で大半を Python へ移すため、比率はさらに下がる
効くのは診断で、読む量はあまり減らない。 bash-language-server は shellcheck を内部で呼んで診断を返す(クォート漏れ・未定義変数・終了コードの扱い)。定義・参照の追跡は関数とファイル内の変数くらいまでに留まる
shellcheck が無いと診断は出ず、何も表示されない (4 と同じ)。devbase の base コンテナには入っていない(which shellcheck で見つからない)。導入は chore: base イメージに shellcheck を入れる(言語サーバによる Bash の診断に要る) devbase#249 で扱う
方針: bash だけの作業項目は立てない。9 の言語の検出に含め、しきい値を超えれば他の言語と同じく設定する。追加するのは shellcheck の有無の検査だけにする。優先は Python > TypeScript / PHP > Bash
作業項目
A. Serena の配布設定を直す(これをやらないと、他をやっても効かない)
B. 使わせる仕組みを作る
C. Claude Code の LSP を用意する(言語は導入先ごとに決める)
D. Codex
E. 他のプロジェクトへ適用できるようにする
受け入れ条件
関連
未確認のこと
PHP は、Serena / LSP のどちらでも型の食い違いが診断されなかった。intelephense の無料版の限界かどうか
Kiro CLI と agy に、同じ仕組みがあるか
hook の遅延(uvx 起動を毎回挟む場合の実測)
「小規模・短時間のセッションでは Serena は持ち出しになる」という第三者の報告があり、私たちのリポジトリで得か損かは A の適用後に測る必要がある
🤖 Generated with Claude Code
何をしたいか
NDF を入れた Claude Code と Codex で
.py/.php/.ts(.js)を扱うとき、定義・参照・診断(型エラー・未解決の import)と、コードを読む量を抑えた編集ができるようにする。方針(実測にもとづく結論)
役割を分け、同じ言語で機能を重複させない。Serena 側の #858 も、重複したツールが並ぶとコンテキストの無駄になると指摘している。
具体例
plugins/ndf/scripts/lib/monitor.py(1,247 行)の_safe_sizeを、例外のときに0ではなく-1を返すよう変え、呼び出し側への影響を調べる。今はReadでファイル全体(48,847 文字)が入り、型の食い違いはpytestを流すまで分からない。調べて分かったこと
1. Serena はほぼ使われていない(手元のセッション記録で実測)
2026-06-24〜09-22 のセッション記録から、
tool_useを集計した。replace_in_files3 /initial_instructions3 /get_symbols_overview2 /activate_project1codex plugin listでmcp-serena@ai-pluginsはnot installedだった。使われなかったのではなく、入っていなかった本来の用途である
find_symbol/find_referencing_symbolsは一度も呼ばれていない。2. なぜ使われなかったか
呼んだ 10 回のうち 7 回が失敗していた。 作業として成功したのは Markdown の文字列置換 1 回だけで、
sedでも済む作業だった。get_symbols_overview×2No active projectで失敗し、以後は呼ばれなかったreplace_in_files→activate_project→replace_in_files×2No active project、2 回目はexpected_countの食い違いで失敗し、3 回目で成功initial_instructions×3原因は 4 つある。いずれも配布設定の不備で、モデルの性質ではない。
/work/ai-plugins/.serena/project.ymlのlanguage_serversは- bashだけで、このリポジトリの.py322 個(約 9 万行)にシンボル機能が効かない。手元の/work/*/.serena/project.yml9 個のうち、言語を設定しているのは 3 個だけだったToolSearchが要り、activate_projectが要り(--project-from-cwdが無いため)、Serena 自身が先にinitial_instructionsを読むよう求めるCLAUDE.mdやエージェント定義には「Serena を活用」とあるだけで、どの場面でgrepではなく Serena を使うかが書かれていない。qa.mdのツール名は古い名前空間mcp__plugin_ndf_serena__*のままで、今のツールに届かないcorderなど)が呼ばれる回数も少ない3. 読み込む量の実測(Claude Code、sonnet-5、同じタスクを 5 条件)
題材は
monitor.py(1,247 行)の_safe_sizeの変更と、呼び出し側への影響の報告。find_symbol/find_referencing_symbols/replace_symbol_bodyLSP(documentSymbol / findReferences)+ 範囲を絞ったRead4 回initial_instructionsだった。これを外せば Serena が有利になる4. Claude Code の plugin LSP servers(実測)
--plugin-dirで LSP 定義だけのプラグインを読み込ませて確認した。system-reminderに<new-diagnostics>として入る(Python のreportOperatorIssue、TypeScript の2362を確認)util.pyの型を変えて壊れた呼び出し側a.pyの分は届かなかったgoToDefinition/findReferences/hover/documentSymbol/workspaceSymbol/goToImplementation/prepareCallHierarchy/incomingCalls/outgoingCalls)。診断を取る操作も rename も無いLSPツールも遅延読み込みで、ToolSearchを 1 回挟むlspServersに宣言したプラグインで.rbを編集したが、警告もエラーも届かず、診断が来ないだけだった。「動いているつもりで動いていない」状態に気付けないため、検査は自前で持つ必要があるtypescript-lspは、案内どおりに入れると動かない。npm install -g typescriptで入る latest は 7.0.2(Go への移植版)でtsserver.jsを持たないため、typescript-language-serverが初期化に失敗する。しかも失敗は表示されず、診断が届かないだけになる。typescript@5に固定すると動いた(Serena は^5.9.3を自分で入れるため、この問題を踏まない)5. Codex には LSP の仕組みが無い(実測)
codex --versionは 0.154.0。codex features listにも設定キーにもlsp系が無い。Codex で LSP を使うには MCP でつなぐしかない。Codex の利用上限のため Codex からは試せず、代わりに MCP クライアントから Serena を直接呼んで確かめた(
--context codex --project-from-cwd)。find_referencing_symbolsget_diagnostics_for_filereportArgumentTypeを返した2345を返した--project-from-cwdを付けると、activate_projectを呼ばずに最初の呼び出しから通る。 ただし、この版ではツール一覧からactivate_projectが消えはしなかった~/.serena/language_servers/static/へ Serena が入れる)ENOENT ... node_modules/package.jsonで初期化に失敗した(symlink が実体のコピーになっていた)。退避して入れ直させると動いた6. Serena 以外の LSP-MCP は、配って使うには弱い
--workspaceの絶対パスも要る)7. 公式の hook で「使わせる」仕組みがある(外部調査)
Serena には公式の hook(
serena-hooks)がある。PreToolUseで grep や Read が続くとpermissionDecision: "deny"を返して Serena の使用を促し、直後にカウンタを戻すため作業は止まらない(閾値は grep 3 回 / コードファイルの Read 3 回 / 混在 4 回、120 秒のクールダウン)SessionStartのactivate、Serena ツールのauto-approve、SessionEndのcleanupもあるmcp__serena__*は、私たちの配布名mcp__plugin_mcp-serena_serena__*に一致しない。 書き換えが要るserena-hooksをuvxで毎回起動すると、ツール呼び出しのたびに遅延が乗る。プラグインに実装を同梱するか、導入時にuv tool install serena-agentを求めるかを決める(未計測)serena prompts print-cc-system-prompt-overrideと hook を勧めている出典: Connecting Your MCP Client / #802 / #858 / plugins reference
8. プロジェクトに依存しない設計にするための実測
このリポジトリ専用の設定にしない。言語は導入先ごとに違うため、検出して設定する形にする。
solidlsp/ls_config.pyのLanguage。python / typescript / php / go / ruby / java / rust / csharp / kotlin / swift / bash / terraform / vue / svelte など)。拡張子との対応も Serena 自身が持つ(Language.get_source_fn_matcher)serena project createの言語推定は、最も多い言語だけを自動で選び、残りは対話で確認する。 複数言語のリポジトリで試すとEnable typescript (28.57% of source files)? [y/N]と聞かれ、非対話ではError: EOF when reading a lineで失敗した。ai-plugins がbashだけになっているのは、この経路を通ったためと見られるserena project create --ls python --ls typescript ...のように--languageを複数回渡せるproject.ymlは正しく検出していた(python / typescript / php のプローブで確認)不要な言語を足したときの代償(混在リポジトリで実測。Python 3 / TypeScript 2 / PHP 1 / bash 1 ファイル)
pythonのみpython+typescript+php+bashfind_symbolinitializeいちばん大きいのは、1 つの失敗が全体を止めることである。 4 言語で試した 1 回目、bash の言語サーバが壊れていた(
Cannot find module './server')ため、Python のfind_symbolまでThe language server manager is not initializedで失敗した。Serena はFailed to start 1 language server(s)で初期化ごと失敗させる。つまり使っていない言語を足すほど、使っている言語の機能が道連れで止まる確率が上がる。手元では TypeScript と bash の 2 つでキャッシュ破損が起きていた。ディスクも増える(intelephense 162MB、bash 48MB、TypeScript 26MB。初回は自動ダウンロードの待ちも入る)。
9. プロジェクトに依存しない仕様(提案)
言語ごとに変わるのは対応表だけにし、手順と hook は言語に依存させない。
(1) 言語の決め方(共通)
git ls-filesの拡張子を数える(追跡対象だけを見る。生成物やnode_modulesを拾わないため)serena project create --ls <言語> ...)(2) 成果物は 3 つ
project.ymlの生成 → 必要な言語サーバの案内 → 動作確認project.ymlの食い違い、未導入の言語サーバを知らせるplugins/ndf/.../languages.json)。拡張子 → Serena の言語識別子 → 公式 LSP プラグイン名 → 言語サーバ本体の導入コマンド、の 4 列(3) Claude Code の LSP は、NDF に定義を持たせない
導入先の言語は分からないため、
lspServersを NDF が固定で持つと、使わない言語の定義が全員に載る。代わりに Skill が検出結果に応じて公式プラグイン(pyright-lsp/typescript-lsp/php-lsp/gopls-lsp/ruby-lspなど)の導入を案内する。4 で分かったとおり、本体が無くても何も表示されないため、Skill 側で導入の有無を検査する。(4) 導入先のリポジトリを汚さない
.serena/project.ymlは導入先に作られる。.gitignoreへ入れるか、追跡するかは導入先の判断とし、Skill は選ばせる(このリポジトリではserena_config.ymlにauth_secretが入る問題がある).worktrees/<ブランチ名>)でも動くこと。--project-from-cwdは最も近い境界を選ぶため、作業ツリー側が有効化される10. ツール名の長さと、起動の仕方(実測)
ツール名は
mcp__plugin_<プラグイン名>_<サーバ名>__<ツール名>である。 小さな MCP サーバを作り、名前を変えて確かめた。.mcp.jsonのサーバ名mcp-serenaserenamcp__plugin_mcp-serena_serena__ping(接頭辞 30 文字)zqzsmcp__plugin_zq_zs__ping(接頭辞 18 文字)zq-long-plugin-nameserena-server-namemcp__plugin_zq-long-plugin-name_serena-server-name__pingmcp__plugin_の部分は固定で、プラグインとして配る限り公式 hook の matchermcp__serena__*には一致しないmcp__serena__*にしたいなら、プラグインではなく利用者の MCP 設定(claude mcp add serena ...)として入れることになる。その場合、プラグインの導入・更新の仕組みから外れるserenaとndfという名前のプラグインを読み込ませたところ、同名の導入済みプラグインがあるためfailedになった。公式マーケットプレイスには Oraios 製のserenaプラグインがあるため、私たちのプラグインをserenaに改名するのは避ける${CLAUDE_PLUGIN_ROOT}は.mcp.jsonで展開され、ラッパースクリプトを起動できる(実測)。したがって「導入済みの Serena があればそれを使い、無ければuvx」は実現できる。initial_instructionsの要求)を踏むためであるuvxの 2 回目以降の起動は 0.8 秒だった(PyPI のserena-agent==1.7.0。git+...は 1.3 秒)。速度のために自動インストールする理由は無い。効くのは初回のダウンロードとオフラインのときuv tool installを走らせるのは避ける。 利用者の~/.localへ書き込み、ネットワークに依存し、失敗しても気付きにくい。導入は Skill の手順(明示的な実行)と、コンテナ側(devbasex/devbase#236)で先に入れておく形にする11. 公式マーケットプレイスの
serenaプラグインを使わない理由(実物を確認)claude-plugins-officialのserena(Oraios 製、community-managed)の実体はanthropics/claude-plugins-publicのexternal_plugins/serenaにあり、中身は.mcp.json1 つだけである。{"serena": {"command": "uvx", "args": ["--from", "git+https://github.com/oraios/serena", "serena", "start-mcp-server"]}}.claude-plugin/plugin.jsonは名前と説明のみで、hook は無い。2025-12-02 以降、更新されていない。git+...の main を追う=現在2.0.0.dev0)。initial_instructionsを要求される破壊的変更を踏むserena-agent==1.7.0に固定--project-from-cwdactivate_projectが要る(2 の失敗 3 回の原因)--contextdesktop-appで、Claude Code 向けのツール除外が効かない)no-memories/no-onboarding公式版は起動引数を変えられないため、hook や Skill を足しても
activate_projectと開発版の問題が残る。 Codex には、そもそも使えない。よってmcp-serenaを維持し、A・B で直す。併存のリスク(推測): 私たちの
mcp-serenaと公式のserenaは名前が違うため、両方入れると Serena が 2 つ起動し、ツールが重複してメモリも 2 倍になると見ている(実測したのは同名プラグインどうしの衝突までで、この併存は未確認)。どちらか一方を選ぶよう案内に書く。上流が起動引数を持つようになったら、乗り換えを再検討する。
12. Bash の扱い(2026-09-23 追記)
.shは 71 個・14,499 行(.pyは 325 個・92,101 行)。hook とplugins/ndf/scriptsに多い。今後のスクリプト化で大半を Python へ移すため、比率はさらに下がるwhich shellcheckで見つからない)。導入は chore: base イメージに shellcheck を入れる(言語サーバによる Bash の診断に要る) devbase#249 で扱う作業項目
A. Serena の配布設定を直す(これをやらないと、他をやっても効かない)
.serena/project.ymlのlanguage_serversにpythonを足す(順序はpython,bash)。ignored_pathsに.worktrees/**を足す.mcp.jsonの版を固定する(serena-agent==1.7.0。今はgit+...の main を引いており、手元で動いた版は2.0.0.dev0だった).mcp.jsonに--project-from-cwdを足す${CLAUDE_PLUGIN_ROOT}/scripts/serena-launch.sh)にし、導入済みの Serena があればそれを使い、無ければuvxで起動する。導入済みの版が想定の範囲かを確かめるserenaへの改名は、公式マーケットプレイスのプラグインと衝突するため避ける--contextをランタイムごとに分ける(Claude Code はclaude-code、Codex はcodex)。今の--context ide-assistantは旧名で、Codex でもclaude-codeとして動いてしまうno-memories/no-onboardingを指定する(CLAUDE.mdの「Serena memory は使用禁止」を、文章ではなく設定として実装する).serena/serena_config.ymlを追跡対象から外す。 生成されるauth_secretが入るファイルである。コミット17d5d441(Fix: 利用者ごとの Serena の設定を追跡から外す)で追跡を外し、.gitignore:54が対象にする。developで追跡している.serena/のファイルは.serena/.gitignoreと.serena/project.ymlだけであるB. 使わせる仕組みを作る
plugins/mcp/mcp-serena/hooks/hooks.jsonの echo 1 行を、実働する hook に置き換える(SessionStart の有効化、PreToolUse の誘導、Serena ツールの auto-approve)。matcher は配布名mcp__plugin_mcp-serena_serena__*に合わせるuv tool install)。ツール呼び出しごとの遅延を計測してから決めるproject.ymlのinitial_promptに、Serena を優先する短い規約を置く(有効化時に必ずモデルへ渡る)refactoring/problem-solving/tdd-cycleなど)にだけ、シンボル単位の手順を書く。文書系の Skill には書かない(.mdは対象外)。書き方は 基盤: Skill の書き方の規約に「スクリプト主体」を足し、検査と本文の量の計測を入れる #855 の規約(SKILL.md は呼び出しと判断だけを持つ)と サブエージェントに Skill 本文を丸ごと読ませず、持ち場で要る手順だけを渡す #828 の worker 向けの抜粋の形に従うserenaと併用しないことと、私たちの版との違い(版の固定・起動引数・hook・Codex 対応)を書くcorder/qa/director/debugger)。qa.mdの古い名前空間mcp__plugin_ndf_serena__*を直し、規約を入れる。corder.mdの Context7 の記述も、このとき扱いを決める。知識系 Skill とエージェント定義の整理(重複・古い節・存在しない参照・判定の誤り) #877(知識系 Skill とエージェント定義の整理)と external-ai / corder / qa-security-scan: 外部 CLI の起動と待ちを external-ai.sh run の 1 行にする #869(corder.mdを最初に置き換える)が同じファイルを触る。どちらで直すかを決めるC. Claude Code の LSP を用意する(言語は導入先ごとに決める)
lspServersを固定で持たせない。Skill が検出結果に応じて公式プラグインの導入を案内する形にするD. Codex
codex plugin add mcp-serena@ai-plugins)。今は入っていない[features] codex_hooks = true、PreToolUse の matcher はBash、PostToolUse でカウンタを戻す)を用意するか決めるE. 他のプロジェクトへ適用できるようにする
git ls-filesの拡張子の集計 → しきい値 →--lsを複数渡して設定)を Skill にする。確認は取らないproject.ymlの食い違い、未導入の言語サーバがあるときだけ知らせる.serena/project.ymlを追跡するかどうかを、導入先で選べるようにする.worktrees/<ブランチ名>)で動くことを確かめる/work/carmo-system-serversideは typescript、/work/carmo-predict-contractは python)受け入れ条件
codex execから、3 言語それぞれで参照検索と診断が使えることを実測する(5 は MCP を直接呼んだ結果で、Codex からは未実測)git ls-files .serenaにserena_config.ymlが出ないことclaude plugin validate .が終了コード 0 で終わる関連
agents/*.md)の整理。B のエージェント定義と同じファイルagents/corder.mdを置き換える未確認のこと
uvx起動を毎回挟む場合の実測)🤖 Generated with Claude Code