speedread について
speedreadは、コーディングエージェント向けのMCPサーバー兼コマンドラインツールで、シンボルを考慮しトークン予算に収まる単位でコードを取得します。リポジトリのマップ、文脈付き検索、関係の追跡、変更を考慮した読み取りにより、コード確認の反復を減らします。
主な機能
- 01予算に応じたリポジトリマップ
- 02シンボルごとにまとめた検索結果
- 03呼び出し元・呼び出し先・参照・実装の追跡
- 04シンボルを考慮した一括読み取り
- 05etagによる変更箇所の読み取り
- 06コマンドラインとJSON Lines出力
活用シーン
- 01コーディングタスクに関連するコードの特定
- 02呼び出し関係と実装の追跡
- 03前回の読み取り以降の変更だけを確認
- 04トークン予算内で大きなファイルを調査
MCP 対応
MCPクライアントに、コード閲覧用の`map`、`search`、`trace`、`read`の4ツールを公開します。コマンドラインツールにも同等の機能があります。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細

speedread
AI コーディングエージェント向けの、トークン効率に優れたコード検索とナビゲーション。 speedread は MCP サーバーと CLI です。Claude Code、GitHub Copilot、Codex、Cursor、Gemini CLI などのエージェントに、トークン予算内で質問に必要なコードベースの部分を提供します。検索ヒットを含む関数、大きなファイルの骨格、シンボルの呼び出し元や実装、前回の読み込み以降に変更された部分だけを返します。ファイル全体や grep のヒットだけを返すことはありません。
コーディングエージェントにとって、Read は適切な抽象化ではありません。 エージェントによるコードの読み取りは、バイト単位ではなく、適応的で、状態を保持し、シンボルを認識し、トークン予算を考慮するべきです。モデル呼び出しのたびに、システムプロンプト、ツール定義、それまでの会話が再送されます(評価では、コードを含める前に 18~21k トークン)。そのためエージェントのコストは、バイト数よりもラウンドトリップ数に左右されます。ripgrep は一致箇所を返し、cat はバイトを返すため、エージェントはファイルを開き、関数を見つけ、次の箇所を検索するために再度問い合わせます。speedread は、質問に役立つコードの最小単位を、次の呼び出しが不要になることも多い十分な構造とともに返します。
| エージェントが必要とするもの | 組み込みツールが返すもの | speedread が返すもの |
|---|---|---|
| あるものの場所 | ファイル名、または一致した行だけ | 各ヒットを、それを囲む関数またはクラスとその行範囲とともに返します(search) |
| 大きなファイル内の 1 つの関数 | 2,000 行ずつのページに分けたファイル、または推測した範囲 | そのシンボルのソース全体(read path#Symbol)、またはファイルの骨格 |
| 呼び出し元、呼び出し先、実装 | 各段階で検索し、その後さらに読み込み | 関係性を 1 回の呼び出しで、最大 3 階層まで返します(trace) |
| 編集後にファイルを再度読むこと | ファイル全体を再度返す | シンボル名を付けて、変更部分だけを返します(read path@etag) |
記録済みの評価トランスクリプトを記録時の速度で再生した、コードに関する 10 個の質問タスクのうち 1 つです。それぞれの条件で、3 回の試行はすべて同じように動作しました。組み込みの grep はファイル名を返すため、エージェントは 2 回、再度質問する必要があります。speedread の search は、一致した行をそれを囲む宣言とともに返します。これは 10 個のタスクのうち 2 番目に大きな削減幅です。2 個のタスクでは約 1% 悪化しましたが、10 個すべてを通じて入力トークンは 35% 減少しました。対話型の完全なレポートはこちらです:brennengreen.github.io/speedread(demo/index.html にも単体で動作する形で収録)。evals/results/ から demo/build.py によって生成されます。
推測ではなく、測定結果
実際のリポジトリで実際のエージェントを使い、両条件で同じモデル(claude-sonnet-5)とハーネス(GitHub Copilot CLI)を使用しています。比較したのは、組み込みツールと、読み取り役としての speedread です。すべての試行、トランスクリプト、採点結果、差分をコミットしており、speedread が役立たなかったワークロードも含まれています。
| ワークロード(実際のエージェント、同じモデルとハーネス) | 条件ごとの試行数 | 入力トークン | モデル時間(中央値) | 品質 |
|---|---|---|---|---|
| コードに関する質問:検索、読み取り、回答 | 30 | −35%(95% CI −45〜−23%) | −47% | pass^3 90% → 100% |
| 関係に関する質問:呼び出し元、呼び出し先、実装 | 8 | −57%(CI −74〜−20%) | −34%(有意差なし) | 100% → 100% |
| バグ修正:検索、編集、テストスイートの実行(ガイダンスあり · 単独) | 16 | −3% · −1%(有意差なし) | −24% · −27%(有意差なし) | 100% → 100%;圧縮によってバグが見えなくなることはありませんでした |
| インストールしたものの、読み取り役にしなかった場合(Q&A · バグ修正) | 10 · 16 | +31% · +46%(タスク10件中9件 · 8件中8件で増加) | — | 26件中0件で使用 |
- 節約を生むのは往復回数です。 speedread はモデル呼び出しを減らすことで節約します。前後のコンテキストを含めた回答、まとめて行う読み取り、1回の処理で完了する
traceがその例です。バグ修正では編集とテストがやり取りの大半を占め、読み取り結果は入力の約1%だったため、トークン数はほとんど変わりませんでした。 - 採用されるかどうかがすべてを左右します。 使用されない MCP サーバーも無料ではありません。ツール定義はすべての呼び出しに含まれます(測定値で呼び出しあたり+2.2kトークン)。読み取り役として設定してください。
- 範囲。 1つのハーネスで1つのモデルを使用しており、関係性とバグ修正のテストスイートは小規模です。他のクライアントやモデルでは未検証のため、この数値は今回の設定での根拠として捉え、ご自身の環境での成果を保証するものではないとお考えください。
pass^3 は、3回の試行すべてに合格したタスクの割合です。区間は平均比に対する95%ブートストラップ区間です(evals/stats.py)。スイートごとの詳細:結果 · 手法:evals/README.md · すべての表:evals/RESULTS.md · 生の試行とトランスクリプト:evals/results/
クイックスタート
1. インストール(Apple Silicon搭載Mac、Rust 1.90以降。クリーンビルドはM4で80秒、ダウンロード時間は別途):
cargo install --locked --git https://github.com/brennengreen/speedread
# or: brew install brennengreen/tap/speedread
ビルド済みバイナリ、ワンクリックで導入できるClaude Desktopバンドル、その他のプラットフォーム、tap名の由来については、インストールを参照してください。
2. エージェントに、ツールをもう1つ追加するのではなく、読み取り役として追加します。 組み込みツールと併用し、ガイダンスを与えずにインストールした場合、使用されず、実行コストが増加しました(上記を参照)。
# GitHub Copilot CLI: add the server, then remove the built-in readers (edit and bash stay)
copilot mcp add speedread -- speedread mcp
copilot --excluded-tools view grep glob
# Claude Code: keep Read, because Edit requires it
claude mcp add --scope user speedread -- speedread mcp
claude --disallowedTools Grep Glob
VS Code、Cursor、Codex、Gemini CLI、Zed、Claude Desktop:設定。組み込みツールを削除できない場合は、AGENTS.md、CLAUDE.md、または.github/copilot-instructions.mdに読み取り手順を追加してください。
3. または、任意のリポジトリで手動で試します:
speedread map --symbols # structure, with each file's top-level definitions
speedread search 'handleRequest' # hits grouped under their enclosing function
speedread trace '#handleRequest' --depth 2 # callers of callers; --direction callees|refs|impls
speedread read 'src/app.ts#Server.start' src/util.ts:40-80 # several targets, one call, one budget
基本機能
MCP経由で利用でき、CLIにも対応する4つのツールです。
| 基本機能 | 役割 | 返される内容 |
|---|---|---|
| map | 構造を特定 | 重要度に応じて絞り込まれた、行数付きのリポジトリツリー。指定するとトップレベルのシンボルも表示 |
| search | テキストを検索 | ripgrepの検索エンジンを使用。すべてのヒットを、それを含む関数またはクラスごとにまとめ、行範囲を表示 |
| trace | 関係性を特定 | 呼び出し元、呼び出し先、参照、実装を特定。構文とレシーバーを考慮 |
| read | 正確な根拠を取得 | トークン予算内で対象と path#Symbols をまとめて取得。path@etag は変更箇所のみを返す |
read:バッチ処理、予算制限、シンボル認識
1 回の呼び出しで、任意のターゲットを組み合わせて指定できます。すべてのターゲットで 1 つのトークン予算を共有します(デフォルトは 8,000)。
| ターゲット | 返される内容 |
|---|---|
src/app.ts | ファイル全体です。収まらない場合は、シグネチャ、型、ドキュメントを含み、関数本体を A-B ⋯ として折りたたんだ スケルトン を返します。それでも大きすぎる場合は、アウトライン を返します。無作為に途中で切ることはありません。 |
src/app.ts:120-180、src/app.ts:120 | 指定された行です。単一行(またはコンパイラーエラーの file:line:col)を指定すると、囲んでいる関数またはクラスを返します。シンボルの外(トップレベルのコード、または文法に対応していない言語)では、インデントや end、} などの閉じ行から特定した、該当箇所を囲むブロックを返します。 |
src/app.ts#handleRequest、#Server.start | ドキュメントとデコレーターを含む、そのシンボルのソース全体です。#Name のみを指定すると、定義をどこからでも検索します。 |
README.md#Install、package.json#scripts | Markdown のセクション、または JSON、YAML、TOML のキーです。 |
src/**/*.test.ts | glob(.gitignore を考慮)です。対象が多い場合は、サイズの大きいものから段階的に内容を絞ります。 |
src/app.ts@<etag> | ヘッダーに表示された etag のバージョンから 変更された部分のみ を返します。 |
flask の 1,628 行の app.py を実際にスケルトン化した例(抜粋)では、ファイル全体の 21k トークンに対し、3.4k トークンで済みます。
==> src/flask/app.py @… (1,628 lines) [skeleton]
110 class Flask(App):
111 """The flask object implements a WSGI application and acts as the central
112-205 ⋯
366 def get_send_file_max_age(self, filename: str | None) -> int | None:
367 """Used by :func:`send_file` to determine the ``max_age`` cache
368-391 ⋯
シンボル認識による再読み込み。 編集後に path@etag を指定すると、unchanged、増加中のログの追加末尾、または変更内容を示す差分が返されます。ハンクには git 形式の関数コンテキストが付き、mode=outline を指定するとシンボルの要約のみが返されます。 tests/mcp.rs より:
==> src/lib.rs @… (was @…): 1 hunk, +1 -1, now 131 lines
symbols:
add [1-7]: body changed, signature unchanged
@@ -2,5 +2,5 @@ add
pub fn add(a: i32, b: i32) -> i32 {
let c = a + b;
- let d = c;
+ let d = c * 2;
let e = d;
シグネチャの編集では f3 [25-27]: signature changed: `pub fn f3() -> u32` → `pub fn f3(k: u32) -> u32` が返され、新しい関数では g [133-135]: added `pub fn g() -> u8` が返されます。
etag は 64 ビットです。 etag はコンテンツの完全な 64 ビット xxh3 で、16 桁の 16 進数として表示されます。エージェントが確認した内容のスナップショットは、etag をキーとする 256 MB の LRU に保存されます。異なる 2 つのコンテンツが同じ 64 ビット値に衝突しない限り、別の内容が同一視されることはありません。1 セッションで 100,000 個のスナップショットがあった場合、その確率は約 3 × 10⁻¹⁰ です。同一のコンテンツは同じ etag を共有しますが、これは正しい動作です。短いタグは、前方一致として扱わずに拒否されます。
search:ヒットを囲んでいるシンボルごとにグループ化
$ speedread search 'def url_for|current_app.url_for\(' src/flask/helpers.py
3 matches in 1 file for /def url_for|current_app.url_for\(/
==> src/flask/helpers.py @5dc322f9c9cf99f2 (3 matches)
[200-251] def url_for(endpoint: str, *, _anchor: str | None = None, _method: str | None = None, _scheme: str | None = None, _external: bool | None = None, **values: t.Any) -> str
200 def url_for(
212 :meth:`current_app.url_for() <flask.Flask.url_for>`. See that method
244 return current_app.url_for(
output=symbols は、同じ呼び出しで、該当箇所を囲むすべての関数のソース全体を返します。output=files は、件数付きのパスを返します。
trace:テキストではなく関係性
コストのかかるエージェントのループは、呼び出しチェーンをたどるために search → open → search again を繰り返します。trace なら 1 回の呼び出しで実行できます。gin での実際の出力(抜粋):
$ speedread trace '#AbortWithStatus' --depth 2
==> callers of Context.AbortWithStatus (context.go:221-227)
func (c *Context) AbortWithStatus(code int)
14 call sites in 14 functions · syntactic: comments, strings and the definition excluded
context.go
[245-251] func (c *Context) AbortWithError(code int, err error) *Error
249 c.AbortWithStatus(code)
← [820-828] func (c *Context) BindUri(obj any) error
824 c.AbortWithError(http.StatusBadRequest, err).SetType(ErrorTypeBind) //nolint: errcheck
…
$ speedread trace Render.Render --direction impls
==> implementations of Render.Render (render/render.go:11-12)
Render(http.ResponseWriter) error
19 implementations of Render · syntactic: types whose method sets cover the interface
render/bson.go [13-16] type BSON
[20-29] func (r BSON) Render(w http.ResponseWriter) error
render/data.go [12-16] type Data
[18-26] func (r Data) Render(w http.ResponseWriter) (err error)
…
4 つの方向があります:
callers:呼び出し元の関数ごとにグループ化した呼び出し箇所です。depthを 2~3 にするとツリーが構築されます。callees:関数本体内の各呼び出しと、解決された定義です。refs:インポートや型への言及を含む、すべての使用箇所です。impls:サブクラス、およびトレイト、プロトコル、インターフェースの実装です。Go のインターフェースは、メソッドセットによって構造的に照合されます。メソッドをターゲットに指定すると、各オーバーライドが列挙されます。
コメントと文字列は tree-sitter によって除外されます。同名の定義は、レシーバー、囲んでいるクラス、Go のパッケージ、ファイルによって区別されます。曖昧さが残る箇所には ? が付けられ、黙って統合されることはありません。これは構文ベースであり、型推論は行いません。制限とロードマップ を参照してください。
map:予算内での概要表示
行数付きの .gitignore 対応ツリーです。予算(デフォルトは 3,000)に達するまで、重要度の高いディレクトリから展開します。ソースが優先され、その後に隠しファイル、テスト、ベンダーの各ツリーが続きます。シンボリックリンクは name → target と表示され、たどりません。
コード実行とスキル
Anthropic の Code execution with MCP では、データがモデルに届く前にフィルタリングする方法が提唱されています。4 つのツール定義に必要なトークンは合計 約 1.4k です。CLI はそれらを再現し、スクリプトを実行するエージェント向けに JSON Lines を追加します:
speedread symbols src --json | jq -r 'select(.kind=="function" and .end-.start>80) | "\(.path):\(.start) \(.qualified)"'
speedread search 'TODO' --json | jq -r .path | sort | uniq -c | sort -rn | head
speedread map --json | jq -s 'map(select(.lines != null)) | sort_by(-.lines) | .[:10]'
skills/speedread/SKILL.md では、ワークフローを Agent Skill としてパッケージ化しています。
結果
ここに記載する数値はすべて、evals/ にある評価から得られたものです。評価は Anthropic の AI エージェントの評価を分かりやすく解説 に基づいて構築されています。具体的なタスク、反復試行、決定論的な結果判定、pass@k と pass^k、対照群を設けたバランスの取れたタスクセット、分離された試行、トランスクリプトの読解を取り入れています。すべてのトランスクリプトを含む生データをコミットしています。エージェントの試行にはすべて、GitHub Copilot CLI 経由で claude-sonnet-5 を使用し、ハーネスの使用状況ログから正確なトークン数を取得しています。概要表では、最も良い結果だけでなく、実際のエージェントを使った4種類すべてのワークロードを取り上げています。
コードに関する質問
Suite 3:6つのリポジトリと5つの言語にわたる、バージョン固有の回答を必要とする10個の質問を、それぞれ3回試行しました。10タスクすべてでコストが減少し、どちらの条件でもツールの結果はほぼ同じサイズでした。削減できたのは、回答ごとに往復が2回減ったことによるものです。唯一のリーダーとして、30回の試行のうち27回で speedread が使われました。残りの3回では、エージェントが41行の go.mod を cat で読みました。このスイートは、trace、シンボル差分、コンテンツを考慮した推定機能が存在する前に実施されました。
関係に関する質問
Suite 3bでは、2ホップの呼び出し元、解決済みの呼び出し先、Go のインターフェース実装(構造的)、Rust のトレイト実装を尋ねます。4つのうち2つは、適切な grep を1回実行すれば回答できるため、対照群としています。事前の指示がない状態で、エージェントは8回の試行のうち7回で trace を選びました。2ホップの質問では、組み込みツールを使うと7~14回のツール呼び出しと186k~277kトークンを要しました。speedread を使った場合、エージェントは depth: 2 を指定して trace を呼び出し、さらに1つの関数を確認して回答しました。呼び出しは2回、トークン数は61kでした。サンプル数は少ない(各群8回の試行)ため、効果の大きさは概算として扱ってください。
トランスクリプトを確認した結果、このスイートの判定基準を変更しました。2ホップのタスクのベースライン試行では、どちらも BasicAuth を除外していました。AbortWithStatus の呼び出しは、ルーターが値として呼び出す BasicAuthForRealm が返すクロージャ内にある、という理由です。これは妥当な解釈であるため、判定基準を変更し、両方の回答を正解として受け入れるようにしました。trace は、クロージャ内の呼び出しを、それを囲む名前付き関数に帰属させます。この点は制限事項に記載されています。
バグ修正(SWE スタイル)
Suite 4 では、gin(Go)と flask(Python)に実際のリグレッションを 8 件埋め込み、症状だけを記したバグレポートをエージェントに渡し、テストを変更せず、リポジトリの全テストスイートで評価します。各タスクは、リグレッションを埋め込んだ状態で失敗し、参照修正を適用すると合格することを検証済みです。4 つの条件は次のとおりです。
- baseline:組み込みツールのみ
- available:speedread をインストールし、指示なし
- preferred:読み取りに使用するようエージェントに求める 1 文の指示
- exclusive:組み込みの view/grep/glob を削除し、edit と bash はそのまま
試行数は合計 64 回です。
- 品質への影響はありません。 64 回中 64 回で合格しました。圧縮によってバグが隠されることはありませんでした。speedread を使用した 32 回の試行のうち、バグのある行そのものより先に、そのファイルが骨格またはアウトラインとして表示されたケースは 0 回でした。エージェントはまず検索し、その後、正確な範囲を読み取りました。
- 採用されるかどうかは二択です。 available は 16 回中 0 回選ばれませんでしたが、8 タスク中 8 タスクで baseline より入力トークンを多く使用しました(+46%;コストは +30%)。1 文の指示を加えると、採用率は 16 回中 16 回となり、読み取りの 78% が speedread 経由で行われました。
- ターン数と時間は減少し、トークン数は横ばいです。 preferred は 8 タスク中 7 タスクでモデル呼び出し回数が少なく(中央値は 6 回から 5 回)、モデル時間が 24% 短縮されました。exclusive ではモデル時間が 27% 短縮され、8 タスク中 7 タスクで短くなりました。コストは 4〜6% 減りましたが、入力トークン数は誤差の範囲内でした(−3%、−1%)。各条件の試行数は 16 回で、これらの区間はいずれもゼロを除外していません。そのため、傾向として捉えてください(統計)。
- 確認できなかったこと: レビュアーが期待していた「コンテキストを 50〜90% 削減しても成功率は同じ」という結果です。読み取りがターンの大部分を占める場合には当てはまりますが、短い編集とテストのループでは当てはまりません。
- この 32 回の試行では
traceは一度も呼び出されませんでした。症状からバグを修正するには、呼び出しグラフではなく、検索と読み取りが必要でした。
ツールレベル
Suite 1 では、実際のリポジトリを対象とした 35 件の読み取りシナリオを扱います。それぞれを情報の十分性で評価します。タスクに必要な情報が欠けている小さな回答は不合格になります。この評価から、プリミティブによって何が圧縮されるかが分かります。また、ファイル全体の読み取りや 2,000 行単位のページングなど、構造上有利な比較もいくつかあります。公平な比較となるのは、名前を grep して関数だけを正確に読み取る best-case のベースラインで、**−46%**となり、呼び出しも 2 回ではなく 1 回です。エージェントの性能を示す根拠は、上記の実際のエージェントを使ったスイートです。
予算の契約
予算はトークン単位ですが、クライアントからサーバーにトークナイザーが伝えられることはありません。Suite 2 では、SVG のパスデータ、JSON、ロックファイル、圧縮された JS、実際の CJK ドキュメント、絵文字、base64、16 進ダンプ、数値テーブルを使って推定器を検証します。o200k、cl100k、従来の Claude トークナイザーでは、固定の 2.6 バイト/トークンの設定だと、読み取りの 9.5% が予算を超過し、最悪の場合は 1.81 倍になりました。コンテンツを考慮する推定器(src/tokens.rs)は、文字クラスからトークン数をモデル化し、o200k と従来の Claude のうち厳しい方に合わせて調整されています。これにより、予算を超過する読み取りは 525 件中 0 件(最悪でも 0.99 倍)です。
本番環境のトークナイザーに合わせて調整済みです。 オフラインのトークナイザーはあくまで代用です。ハーネスはモデル呼び出しごとの正確な入力トークン数を記録するため、連続する呼び出しから各ツールの結果にかかる実際のコストを算出できます(Suite 2b)。claude-sonnet-5 では、実際のトークン数は中央値で推定値の 1.22 倍、speedread 自身の出力では 1.36 倍です。これは、Claude 4.7 以降のトークナイザーではトークン数が約 30% 増えるという Anthropic の説明と一致します。Claude として識別されるクライアントには、予算を 1.4 倍に調整する Claude プロファイルが適用されます。SPEEDREAD_TOKENIZER=claude でどこでも強制できます。ほかのプロファイルは openai と legacy です。
速度
速度が最大の売りではありません。返す情報を減らすことが重要です。それでも、解析、グループ化、予算設定など、呼び出しごとにより多くの処理をしても、レイテンシが増えないことは重要です。Apple M4(4P + 6E コア)でウォームキャッシュを使用した場合の中央値です。
| タスク | speedread | ripgrep のデフォルト | ripgrep -j4 |
|---|---|---|---|
| vscode を走査(19,167 ファイル、サイズと更新時刻を含む) | 26 ms | 29 ms(名前のみ) | 30 ms |
| vscode で文字列を検索 | 103 ms | 294 ms | 109 ms |
742 KB、21k 行の .d.ts を読み取り → スケルトンを生成(コールドプロセス) | 17 ms | ||
vscode 全体から #createDecorator の定義を検索 | 332 ms |
ripgrep にパフォーマンスコアのみを使うよう指定すると、検索速度は ripgrep と同等です。ripgrep のデフォルト設定に対する 2.9 倍の差は、このチップでスレッドが効率コアにも割り当てられることによるもので、カーネル時間は 6.6 倍に増加します。speedread は hw.perflevel0.logicalcpu に基づいてスレッドプールのサイズを決めます。
他との比較
ほかの MCP サーバーも、この機能の一部を提供しています。公式の filesystem サーバー はファイル全体の読み取りをまとめ、行数で制限します。Serena は言語サーバーを通じてシンボルを認識します。ast-grep MCP は構造検索を行い、claude-context は埋め込みによる検索を行い、repomix はリポジトリ全体を 1 つのファイルにまとめます。speedread は、単一のトークン予算内でバッチ処理されたシンボル認識型の読み取りに、差分のみの再読み取りと関連性クエリを組み合わせており、埋め込みも言語サーバーも必要ありません。出典付きの機能表は docs/RESEARCH.md にあります。
インストール
ソースからインストール(Rust 1.90 以降。brew install rust または rustup を使用します。tree-sitter の文法には C コンパイラーも必要です。Xcode の Command Line Tools で利用できます):
cargo install --locked --git https://github.com/brennengreen/speedread # or, in a clone: cargo install --locked --path .
実行時の依存関係がないネイティブバイナリ ~/.cargo/bin/speedread がインストールされます。--locked は、CI でテストされている Cargo.lock 内の依存関係バージョンをビルドします。
**ビルド済みバイナリ、Apple Silicon 搭載の macOS 向け:**各リリースには、バイナリとその SHA-256 が添付されています。
mkdir -p ~/.local/bin # or any directory on your PATH
curl -fsSL https://github.com/brennengreen/speedread/releases/latest/download/speedread-aarch64-apple-darwin.tar.gz | tar -xz -C ~/.local/bin
バイナリは公証されていません。curl は macOS の隔離フラグを設定しません。ブラウザーでダウンロードした場合は、xattr -d com.apple.quarantine speedread で解除してください。
Claude Desktop、ワンクリック:speedread-aarch64-apple-darwin.mcpb をダウンロードして開きます。Claude Desktop は speedread が読み取り可能なフォルダーを尋ねます。そのフォルダー外の読み取りは拒否されます。
Homebrew:brew install brennengreen/tap/speedread はソースからビルドします。完全な名前を使用してください。brew install speedread だけを実行すると、homebrew-core にある別のプログラム(RSVP 速読ツール)がインストールされ、speedread バイナリも別途インストールされます。
MCP Registry:io.github.brennengreen/speedread(mcp-name: io.github.brennengreen/speedread)として登録されているため、レジストリー対応クライアントはバンドルを検索してインストールできます。エージェントに speedread をインストールしてもらう場合は、llms-install.md を参照してください。
新しいバージョンは、リリースノート付きでリリースとして公開されます。通知を受け取るには、Watch → Custom → Releases を選択してください。
プラットフォームのサポート
| プラットフォーム | 状況 |
|---|---|
| Apple Silicon 搭載の macOS | ビルド、チューニング、テスト済みです。CI では macOS 15 上で、両方のディレクトリウォーカーを使ってテストスイートを実行します。 |
| Intel 搭載の macOS | 同じコードを使用します。テストスイートは Rosetta 2 上で x86_64 ビルドとして合格しています。Intel ハードウェアおよび CI では、まだテストされていません。 |
| Linux | テストスイートは Ubuntu 24.04(x86_64)で合格しており、CI ではプッシュのたびに実行されます。macOS 固有のコードはコンパイル対象から除外され、ポータブルなウォーカー(ignore クレート)が使用されます。Linux 向けのチューニングやベンチマークは行われておらず、ビルド済みバイナリもまだありません。cargo でインストールしてください。他のディストリビューションや arm64 での動作報告も歓迎します。 |
| その他の Unix | 未テストです。Linux のコードパスが適用されます。 |
| Windows | サポートされていません。コードが Unix 専用の API を使用しています。WSL2 の状況は Linux と同じです。 |
結果に記載されている速度の数値は、Apple M4 で測定したものです。
読者として使う
利用可能であることと、実際に使われることは別です。ガイダンスなしで組み込みツールと並べてインストールした場合、2つのスイートでの26回の試行のうち、speedreadが使われたのは0回でした。また、speedreadのツール定義はモデルを呼び出すたびに送られるため、これらの実行ではインストールしない場合よりコストが増えました(入力トークンが+31%と+46%)。ガイダンスを一文加えるだけで、16回中16回で使われるようになりました。そのため、speedreadは多数ある選択肢の一つではなく、読者として設定してください。
**GitHub Copilot CLI:**サーバーを追加してから、組み込みの読み取りツールを削除します。Editとbashは残します。
copilot mcp add speedread -- speedread mcp
copilot --excluded-tools view grep glob
Claude Code:
claude mcp add --scope user speedread -- speedread mcp
claude --disallowedTools Grep Glob # keep Read: Edit requires it
Claude Codeに関する注意点(数値付き)。 Claude Codeの
Edit/Writeを使うには、事前にそのファイルをネイティブのReadで読み込む必要があります。MCPによる読み取りは対象外です(claude-code#32214、対応予定なしとしてクローズ)。speedreadではこの読み取りを省略できません。バグ修正スイートでは、speedreadのエージェントはspeedread経由でしか見ていないファイルを編集しました。各ファイルをデフォルト設定のReadで全体読み込みすると2,000~21,000トークン(中央値9,800)かかり、その後のすべてのターンで再送されます。これを加えると(上限値として)、ベースラインに対する入力トークンの優先差分は−3%から**+10%に、専用差分は−1%から+19%**になります。ベースラインは変わりません。これらのファイルは、もともとネイティブの方法で読み込まれていたためです。編集箇所を範囲指定してReadすればチェックを満たせる可能性が高いですが、未検証です。Claude Codeでは、編集の多い作業でspeedreadがターン数と時間を節約することは期待できますが、トークンの節約は期待できません。前述の探索と関連性に関する節約効果は引き続き得られます。
VS Code、Cursor、Codex、Gemini CLI、Zed、Claude Desktop:設定を参照してください。これをAGENTS.md、CLAUDE.md、または.github/copilot-instructions.mdに追加します。
## Reading code
Use the speedread MCP tools to read, search and navigate code; use built-in tools only to edit and run commands.
- `read` everything you need (files, `path:A-B`, `path#Name`, `#Name`) in ONE call; expand skeletons with `path#Name`.
- `search` finds text (hits show their enclosing function); `trace` follows callers, callees and implementations.
- After editing, `read path@etag` to see only what changed.
設定
speedreadはstdio経由でMCPを提供します(speedread mcp)。ワークスペースのルートは、--root <dir>(複数回指定可能)、次に$CLAUDE_PROJECT_DIR、次にクライアントのMCPルート(VS Code/Cursorのフォルダー、Claude Codeの--add-dir)、最後にカレントディレクトリの順に決まります。通常はフラグを指定する必要はありません。
| クライアント | 設定 |
|---|---|
VS Code(.vscode/mcp.json) | { "servers": { "speedread": { "type": "stdio", "command": "speedread", "args": ["mcp"] } } } |
Cursor(~/.cursor/mcp.json) | { "mcpServers": { "speedread": { "command": "speedread", "args": ["mcp"] } } } |
Codex CLI(~/.codex/config.toml) | [mcp_servers.speedread] · command = "speedread" · args = ["mcp"] |
Gemini CLI(~/.gemini/settings.json) | { "mcpServers": { "speedread": { "command": "speedread", "args": ["mcp"] } } } |
Zed(settings.json) | { "context_servers": { "speedread": { "source": "custom", "command": "speedread", "args": ["mcp"] } } } |
| Claude Desktop | .mcpbバンドル(ワンクリック)、またはバイナリの絶対パスと"args": ["mcp", "--root", "/path/to/project"] |
GUIアプリはシェルのPATHを引き継がない場合があります。which speedreadで確認できる絶対パスを使用してください。
環境変数:
SPEEDREAD_TOKENIZER=claude|openai|legacyは、トークン数の予算調整を固定します(デフォルト:クライアントから検出し、検出できない場合はlegacy)。SPEEDREAD_THREADSはワーカー数を設定します(デフォルト:パフォーマンスコア数)。SPEEDREAD_WALKER=portableはポータブルウォーカーを使用します。
制限事項とロードマップ
traceは構文解析に基づきます。 tree-sitter と、レシーバー、クラス、パッケージによる名前解決を使用しますが、型推論は行わないため、レシーバーが不明なx.f()はすべてのfに一致し、?が付与されます。クロージャーやラムダ内の呼び出しは、外側の名前付き関数に帰属し、値として渡された関数は呼び出しとして扱われません。次の段階として、正確な参照、オーバーライド、呼び出し階層に対応する、同じtraceインターフェースの背後にあるオプションの LSP/SCIP レイヤーを追加します。- 定義によるオーバーヘッドと導入。 このサーバーは、使用するかどうかにかかわらず、すべてのモデル呼び出しに約2.2kトークンを追加します(view/grep/glob を置き換える場合は、差し引き+0.9kです)。より簡潔な説明、プロンプトなしでの導入を促すツール名と説明の A/B テスト、map、search、trace、read のいずれかを自動選択する単一の高レベルな
contextツールが、次の課題です。 - サンプル数。 バグ修正と関係性のテストスイートでは、各群の試行数はそれぞれ16回と8回で、バグ修正におけるトークン数と所要時間の差はノイズの範囲内です。タスク、試行回数、その他のハーネス(Claude Code、Codex)を増やすことが次の課題です。
- 予算は推定値であり、トークナイザーで数えた値ではありません。オフラインのトークナイザーと、本番の計測値に基づく Claude プロファイルを使って調整しています。
- Apple Silicon 搭載の macOS 向けにビルドし、調整しています。Linux は CI でテストスイートに合格しますが、調整はしていません。Intel 搭載の macOS は CI に含まれていません。Windows はサポートしていません。プラットフォームのサポートを参照してください。
これらの各項目について、対象範囲、必要なスキル、推奨される最初のステップをROADMAP.mdにまとめています。
セキュリティ
設計上、読み取り専用です。書き込みツールはありません。パスは正規化され、ルート内にある必要があります。依存関係のキャッシュ(~/.cargo/registry、~/go/pkg/mod、SwiftPM のチェックアウト、SDK)は読み取り可能です。--no-deps を指定するとこれを無効にでき、--unrestricted を指定するとすべてのパス制限が解除されます。macOS のプライバシー保護は引き続き適用されます。脆弱性は非公開で報告してください。SECURITY.mdを参照してください。
動作の仕組み
- 予算の段階的調整。 各対象には4種類の表示形式があります。完全表示、スケルトン、簡易スケルトン(コメント、ドックストリング、import の連続部分を折りたたむ)、アウトラインです。バッチに収まるまで、項目をサイズの大きいものから順に簡略化します。探索的な対象は指定されたシンボルより先に簡略化し、明示的に指定された範囲は決して簡略化しません。最後に、トップレベルのシンボルをすべて残したうえで、メンバーを幅優先で追加するアウトラインを作成します。応答はコンテンツを考慮した推定値でサイズを調整し、送信前にもう一度確認します。最大予算(10k)により、すべてのクライアントで結果がインラインに収まります。Copilot CLI は30 KBを超える結果をファイルに出力し、Claude Code は10kトークンを超えると警告します。
- アウトライン。 tree-sitter は Rust、Python、JavaScript、TypeScript/TSX、Go、Java、C、C++、C#、Ruby、PHP、Bash、Swift、Kotlin、Scala、Lua、Luau(
.luauおよび Luau 構文を使用する.luaファイル)、Objective-C に対応しています。Markdown、JSON、YAML、TOML は単一パスのスキャナーで処理します。Objective-C と C のヘッダーは、解析前に Apple SDK のマクロを空白にします。そうしないと、tree-sitter のエラー回復処理によってファイルの残りの部分が無視されます。文法が対応する以前から存在する@nativeなどの Luau 属性も、同じ方法で空白にします。 - キャッシュ。 ソースは、アクセスのたびに(サイズ、mtime ns、inode、デバイス)で検証します。アウトラインはコンテンツハッシュをキーにキャッシュされ、長時間稼働する MCP プロセスでは両方のキャッシュが保持されます。
- macOS。
getattrlistbulk(2)を使うウォーカーは、複数のエントリーの名前、種類、サイズ、mtime、フラグを1回のシステムコールで取得します。readdir+lstat より1.8倍高速です。- ワーカープールのサイズはパフォーマンスコア数に合わせ、
QOS_CLASS_USER_INITIATEDで実行します。 - iCloud のデータ未取得ファイルは、ダウンロードせずに即座に失敗します(
IOPOL_TYPE_VFS_MATERIALIZE_DATALESS_FILES)。 - launchd が GUI から起動したプロセスに設定するファイル記述子のソフト上限256を引き上げます。
- キャッシュファイルには mmap を使用しません。エディターがファイルをその場で切り詰めると SIGBUS が発生するためです。
- NEON
memchr、simdutf8、xxh3、mimalloc。
各設計上の判断の背景となる調査と出典は、docs/RESEARCH.mdにあります。
貢献
Issues、評価結果、プルリクエストを歓迎します。speedread が役に立たなかった結果も含みます。セットアップに関する質問やアイデアは、Discussions に投稿してください。取り組みやすい項目をいくつか紹介します。
- Linux: CI ではテストが通っています。実環境での報告を歓迎します。小さな修正から始めるなら、macOS 専用の 5 つのヘルパーにより、そこで clippy が失敗します。
- その他のハーネスとモデル: Claude Code、Codex、Cursor、Gemini CLI は上記で設定されていますが、まだ測定されていません。評価結果を共有してください。
- 言語とクライアント: 解析がうまくいかない言語のアウトライン用フィクスチャ、またはクライアント向けに動作確認済みのセットアップ。
CONTRIBUTING.md では、セットアップ、テスト、言語の追加方法に加え、このプロジェクト固有のルールを説明しています。ツールの説明とサーバーの指示はモデルが読み取るため、変更すると採用状況が変わる可能性があり、評価が必要です。ROADMAP.md には、初めての貢献に適した項目を含む、範囲を絞った作業が記載されています。
開発
cargo test # unit, MCP protocol and outline snapshot tests
cargo fmt --check && cargo clippy --all-targets -- -D warnings # CI's other checks
UPDATE_SNAPSHOTS=1 cargo test --test outlines # after an intentional outline change
python3 evals/tool_eval.py <bench> --speedread target/release/speedread --rg rg
python3 demo/build.py # regenerate the demo and README charts from evals/results
ライセンス
MIT © 2026 Brennen Green
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。