indexio について
indexioは組織のリポジトリをインデックス化し、高速な字句・セマンティック・ハイブリッド検索、シンボル検索、呼び出しグラフ分析を提供します。データベースや外部サービスを使わず、ローカルで持ち運べるコードコンテキストを必要とする開発者やコーディングエージェント向けです。
主な機能
- 01字句・セマンティック・ハイブリッド検索
- 02シンボル定義と呼び出しグラフ
- 03シンボルと差分の影響分析
- 04リポジトリとコードフォルダーのインデックス化
- 05インクリメンタル同期
活用シーン
- 01識別子や概念からコードを検索
- 02シンボル変更前に呼び出し元を追跡
- 03コーディングエージェントに検索可能なリポジトリ情報を提供
MCP 対応
indexioはstdio経由のMCPサーバーとして動作し、コード検索、シンボル検索、ファイル読み取り、影響分析のツールを公開します。HTTP APIも提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
13掲載時のツール一覧 · 6 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| mode | enum | いいえ | lexical | semantic | hybrid |
| limit | integer | いいえ | 最大結果数(デフォルト 50) |
| lines | integer | いいえ | lexical:ファイルあたりの一致行数(デフォルト 1、最大 100) |
| query | string | はい | 検索クエリ |
| fusion | enum | いいえ | hybrid のみ(デフォルト rrf)rrf | combmnz |
| rerank | boolean | いいえ | hybrid のみ(デフォルト false)。rerank エンドポイントの設定が必要です。未設定の場合は効果がありません。 |
詳細
indexio
indexio は AI コーディングエージェント向けのコード検索エンジンです。組織内のすべてのリポジトリを一度だけインデックス化します。クエリにはミリ秒単位で回答します。インデックスを、Model Context Protocol(MCP)経由のツールおよび HTTP API としてエージェントに提供します。
indexio は Rust で書かれた単一のバイナリです。データベースや外部サービスは必要ありません。インデックスは、1 つのデータディレクトリ内のファイル群です。そのディレクトリを別のマシンにコピーできます。
エージェントにインストールしてもらう
以下のブロックを、Claude Code、Cursor、Codex、またはシェルコマンドを実行できる任意のコーディングエージェントに貼り付けてください。indexio をインストールし、コードをインデックス化して、MCP サーバーを登録し、結果を検証します。~/code をリポジトリを格納しているフォルダーに置き換えてください。
Install indexio (https://github.com/IOServicesLabs/indexio) on this machine and connect it
to me. Do these steps in order and stop at the first failure with the exact error.
1. Install the binary.
- Linux or macOS: curl -fsSL https://raw.githubusercontent.com/IOServicesLabs/indexio/main/install.sh | sh
- Windows (PowerShell): irm https://raw.githubusercontent.com/IOServicesLabs/indexio/main/install.ps1 | iex
- If neither works, use `pip install indexio-cli`, `npm install -g indexio`, or `cargo install --git https://github.com/IOServicesLabs/indexio indexio`.
The binary lands in ~/.local/bin (Linux, macOS) or %LOCALAPPDATA%\Programs\indexio (Windows).
If `indexio --version` is not found afterwards, add that folder to PATH and open a new shell.
`git` must be on PATH.
2. Index my code: indexio add ~/code
This registers every git repository under the folder at any depth and builds the index.
Nothing is uploaded; the index lives in ~/.indexio.
3. Register the MCP server with the agent you are.
- Claude Code: indexio setup claude --claude-md ~/.claude/CLAUDE.md
then indexio hook install
(the hooks route file reads and greps through the index; scripts and builds run as before)
- Any other MCP client: add this server to its MCP configuration and restart the client:
command: indexio args: ["mcp"]
Use the absolute path of the binary if the client does not search PATH.
4. Verify. All four must succeed:
- indexio --version prints a version
- indexio stats lists the repositories and a file count above zero
- indexio search "TODO" --limit 3 returns hits from my code
- indexio usage prints a report (it is empty until I use the tools)
5. Tell me what was installed, where the data directory is, which repositories were
indexed, and that I must restart my agent session so it picks up the new MCP server.
Do not modify any file inside my repositories.
エージェントはその後、code_search、code_grep、find_symbol、who_calls、file_outline、read_span、impact_of_symbol、impact_of_diff、recall をツールとして利用でき、インデックスに基づいた回答をミリ秒単位で得られます。ツール一覧で各ツールについて説明しています。
インストール
いずれかを選択してください。どの方法でも indexio コマンドを利用できます。
| プラットフォーム | コマンド |
|---|---|
| Linux、macOS | curl -fsSL https://raw.githubusercontent.com/IOServicesLabs/indexio/main/install.sh | sh |
| Windows(PowerShell) | irm https://raw.githubusercontent.com/IOServicesLabs/indexio/main/install.ps1 | iex |
| npm(任意のプラットフォーム) | npm install -g indexio |
| pip(任意のプラットフォーム) | pip install indexio-cli |
| Docker | docker pull ghcr.io/ioserviceslabs/indexio |
| Homebrew、winget | まだ対応していません。上記のスクリプトまたはパッケージを使用してください |
| ソースからインストール(Rust 1.85 以降) | cargo install --git https://github.com/IOServicesLabs/indexio indexio |
スクリプトと npm パッケージは、お使いの OS と CPU に対応する最新のリリースのバイナリをダウンロードし、SHA-256 を検証します。pip のホイールにはバイナリが含まれており、プラットフォームごとに 1 つのホイールがあります。PyPI では indexio が無関係な別のプロジェクトに使われているため、pip パッケージ名は indexio-cli です。インストールなしでコンテナイメージを利用できます。Docker でのデプロイを参照してください。git が PATH 上にある必要があります。サービス、データベース、モデルのダウンロードは不要です。
アップグレード
同じインストールコマンドをもう一度実行します。~/.indexio 内のインデックスは維持されるため、再インデックスは不要です。
| インストール方法 | アップグレードコマンド |
|---|---|
| スクリプト、Linux または macOS | curl -fsSL https://raw.githubusercontent.com/IOServicesLabs/indexio/main/install.sh | sh |
| スクリプト、Windows | irm https://raw.githubusercontent.com/IOServicesLabs/indexio/main/install.ps1 | iex |
| npm | npm install -g indexio@latest |
| pip | pip install -U indexio-cli |
| Docker | docker pull ghcr.io/ioserviceslabs/indexio:latest を実行し、続いてコンテナを再作成します |
| ソース | cargo install --git https://github.com/IOServicesLabs/indexio indexio --force |
続いて、さらに 2 つの手順を実行します。
indexio hook installを実行します。新しいバージョンで追加されたフックを導入し、ほかのフックを修復します。独自のフックは保持されます。- エージェントのセッションを再起動します。実行中のセッションは、再起動するまで indexio サーバーを使い続けます。
実行中のセッションがあっても、アップグレードは可能です。
- 2 つのスクリプトは、セッションがバイナリを使用している間に置き換えます。Windows では、
install.ps1が実行中のindexio.exeをindexio.old.exeに移動し、新しいバイナリをコピーします。 - Windows では、npm と pip はバイナリをその場で上書きしようとしますが、実行中のファイルは Windows によって上書きが許可されません。先にエージェントのセッションを終了するか、スクリプトを使用してください。
- 古いバージョンのまま実行中のセッションでも、新しいバージョンが書き込んだインデックスを読み取れます。
- 最初に起動する新しいサーバーは、初回のみの処理をバックグラウンドで実行します。ベクトルがないファイルを埋め込み、セッションカードを書き込みます。呼び出しがブロックされることはありません。
クイックスタート
コマンドは 3 つです。3 つ目は Claude Code 専用です。
indexio add ~/code # 1. index every git repository under a folder
indexio search parse_config # 2. search it (add --mode hybrid for a question in words)
indexio setup claude # 3. register the MCP server with Claude Code
続いて、Claude Code を再起動します。セッションで indexio のツールを使えるようになります。任意のコマンドを 2 つ実行すると、さらに節約できます。
indexio hook install # reads and greps of indexed files go through the index
indexio sync # run from cron or a timer to keep the index current
indexio stats では、インデックス化された内容を確認できます。indexio usage では、インデックスが提供したトークン数と、組み込みツールが返したであろうトークン数を比較できます。
すべてのデータは、単一のディレクトリに保存されます。--data-dir、$INDEXIO_DATA_DIR、または ~/.indexio です。
目次
- エージェントにインストールさせる
- indexio の機能
- ソースを追加する
- インデックスを最新に保つ
- 埋め込み
- インデックス化されないもの
- HTTP API を保護する
- チームでのインデックス化:ライブ worktree オーバーレイ
- エンタープライズ向けセットアップ
- Claude Code で indexio を使う
- トークンの節約量を測定
- 影響分析
- ほかのツールから indexio を使う
- コマンドリファレンス
- 環境変数
- Docker でデプロイする
- アーキテクチャ
- 実測パフォーマンス
- 制限事項
- 開発とリリース
indexio の機能
indexio は、組織のコードに関する 3 種類の質問に回答します。
| 種類 | 例 | 方法 |
|---|---|---|
| 字句検索 | WalkState::new はどこで定義されていますか? /fn parse_*/ に一致する Rust ファイルはどれですか? | トライグラムインデックス、正規表現、完全一致の識別子 |
| 意味検索 | プリンターの出力をバッファリングする方法は? 認証トークンはどこで更新しますか? | 構文を考慮したコードチャンクに対するベクトル検索 |
| ハイブリッド | どんな質問でも | 字句検索、BM25、意味検索の結果を、相互順位融合(RRF)で統合 |
indexio は、コードの定義とコールグラフも把握しています。シンボルの定義場所、呼び出し元、変更した場合に影響を受ける箇所を確認できます。
ソースを追加する
各 add はソースをただちにインデックス化し、セマンティックプレーンを構築します。
indexio add ~/code # every git repository under the folder, at any depth
indexio add /srv/checkouts/legacy-monolith # a folder without git: indexed as-is
indexio add github:my-org # a GitHub organization or user
indexio add github:my-org/payments # one GitHub repository
indexio add azdo:my-org/Platform # an Azure DevOps project
indexio add https://gitlab.example.com/g/r.git # any git host
検索するには:
indexio search parse_config
indexio search "how is backpressure applied" --mode hybrid
インデックスをエージェントに提供するには:
indexio mcp # MCP over stdio
indexio serve # HTTP API on http://127.0.0.1:7717
indexio は各ソースを <data-dir>/sources.json に記録します。indexio sources はソースと登録済みのリポジトリを一覧表示します。indexio remove <source> はソースの登録を解除します。
add で役立つフラグ:--limit 20(大規模な組織での試験実行用)、--include-forks、--include-archived、--full-clone、--dest DIR(リモートクローンの保存先)、--no-embed、--exclude PATH、--pdf-text。
リポジトリやその他のファイルを含むフォルダー。 フォルダーには、Git リポジトリと、どのリポジトリにも属さないファイル(メモ、仕様書、エクスポート、PDF など)が含まれていることがよくあります。indexio add は各リポジトリをリポジトリとしてインデックス化し、その他のファイルはフォルダー名を付けた追加のリポジトリとしてインデックス化します。
projectA/ indexio add ~/projectA
├── backend/ (git) → repository "backend"
├── frontend/ (git) → repository "frontend"
├── docs/notes.md → repository "projectA": the contents
├── docs/spec.pdf → repository "projectA": the name only
└── old-copy/ → left out with --exclude old-copy
- テキストファイルは、サイズ制限(テキストは 256 KiB、コードは 4 MiB)まで内容をインデックス化します。
- ドキュメント(PDF、Word、Excel、PowerPoint、OpenDocument、RTF、EPUB)と、サイズ制限を超えるテキストファイルは、名前のみをインデックス化します。
list_filesと名前に含まれる語句での検索で見つけられます。ファイルに対するread_spanは、内容がインデックス化されていないことを示します。ファイル自体を読み取ってください。フックを使うと、このようなファイルの読み取りが可能です。 --pdf-textを指定すると、これらの PDF の名前ではなくテキストレイヤーをインデックス化します。ドキュメント(Word、Google Docs、ブラウザー)からエクスポートされた PDF にはテキストレイヤーがあるため、検索で内部の語句を見つけられます。スキャンされた PDF にはテキストレイヤーがないため、名前のみのエントリーのままです。indexio は OCR を行いません。抽出されたテキストにはテキストのサイズ制限が適用されます。64 MiB を超える PDF、または読み取りに 20 秒を超える PDF は、名前のみのエントリーのままです。このオプションはソースとともに記憶されます。- 画像、メディア、アーカイブ、その他のバイナリファイルはインデックス化されません。
--exclude PATH(繰り返し指定可能。フォルダーからの相対パス)を指定すると、フォルダーを除外できます。除外されたフォルダーはリポジトリとして扱われず、その中のファイルもインデックス化されません。除外設定はソースとともに記憶され、addを再実行すると追加されます。- 単独で登録されたフォルダーが重複してインデックス化されることはありません。
認証情報。 indexio は環境変数からのみ認証情報を読み取ります:GITHUB_TOKEN(または GH_TOKEN)と AZDO_TOKEN(または AZURE_DEVOPS_EXT_PAT、SYSTEM_ACCESSTOKEN)。認証情報は一覧取得 API と git に認証ヘッダーとして送信されます。クローン URL、ログ、.git/config に保存されることはありません。パブリックリポジトリにはトークンは必要ありません。
インデックスを最新の状態に保つ
cron またはタイマーから indexio sync を実行します。たとえば、15 分ごとに実行します。各実行は
増分処理です。
- 新しいリポジトリはクローンされます。
- 変更された git リポジトリは、コミット単位で差分インデックス化されます。
- 変更された通常のフォルダーは、コンテンツハッシュ単位で差分インデックス化されます。
- 新規および変更されたチャンクは埋め込み処理されます。それ以外のチャンクはすべてキャッシュヒットになります。
156 個のリポジトリと 17,530 個のファイルからなるフォルダーツリーは、変更がない場合、11 秒で同期されます。
実行中の indexio mcp サーバーは、さらに自動で次の処理を行います。
- セッションが作業するリポジトリを監視します。ファイルに変更がある場合は、各呼び出しの前に作業ツリーを再インデックス化します。コミット前および未追跡の編集内容はすぐに検索可能になり、数百ミリ秒以内にバックグラウンドスレッドで埋め込み処理されます。
- 10 分ごとに、ほかのリポジトリの HEAD が移動したか確認し、移動したリポジトリを再インデックス化します。また、変更された通常のフォルダーはコンテンツに基づいて再インデックス化されます(初回の処理後は、変更のないファイルには stat が 1 回必要なだけです)。
- フォルダーが登録される前に開始したセッションは、
indexio addから 1 分以内にそのリポジトリを認識します。再起動は不要です。 - チェックアウトが未登録でも、登録済みのリポジトリが 3 つ以上並ぶ場所にあるセッションは、そのチェックアウトを自動で追加します(git リポジトリ、または最大 20,000 個のファイルを含む通常のプロジェクトフォルダーが対象です。リポジトリを格納するフォルダーは対象外です)。無効にするには、
INDEXIO_NO_AUTO_ADDを設定するか、<data_dir>/auto-add-skipを作成します。 read_span、code_grep、code_search、またはfile_outlineの応答が、このセッションで過去 20 分以内に取得したものと同一の場合、1 行のメモが返されます。同じ呼び出しを再度送ると全文が返され、コンパクションまたは/clearでこの状態がリセットされます。
埋め込み
組み込みモデル
デフォルトの埋め込みモデルは Random Indexing(rindex)です。これは、indexio がユーザー自身のコードから、CPU 上で 1 回のストリーミング処理によりプロセス内で構築するセマンティックモデルです。トレーニング用のインフラストラクチャも、ダウンロードも、GPU も必要ありません。事前学習済みモデルが知らない、組織内のサービス名、コードネーム、API の語彙を学習します。
新しいチャンクはそれぞれ増分更新されるため、indexio sync の処理コストを低く抑えられます。
難易度の高い概念クエリ 20 件(bench/)で測定した結果、ハイブリッド検索の recall@5 は 60 %、MRR は 0.397 です。
同じクエリで、語彙検索のみの場合はそれぞれ 5 %、0.050 です。
オプションのニューラルエンドポイント
検索品質を最大限に高めるには、vLLM または TEI 上の Qwen3-Embedding など、OpenAI 互換の任意の埋め込みエンドポイントを indexio に指定します。2 つのモデル名前空間は共存できます。
export INDEXIO_EMBED_BASE=http://embed.internal.example:8080
export INDEXIO_EMBED_MODEL=Qwen/Qwen3-Embedding-8B
export INDEXIO_EMBED_DIM=1024
export INDEXIO_EMBED_KEY=... # only if the gateway needs it
indexio embed # builds vec/<model-id>.*.civec
埋め込みは (chunk hash, model id) によってコンテンツアドレス指定されます。1 つのファイルを共有する 2 つのリポジトリは、その埋め込みも共有します。組織内でチャンクが重複しても、追加コストはかかりません。
オプションの再ランキングモデル
TEI または vLLM 上の Qwen3-Reranker など、再ランキングエンドポイントを追加します。クエリで指定すると、indexio はこれを使用します。指定方法は、indexio search --mode hybrid --rerank、HTTP の rerank=1、または MCP の rerank: true です。エンドポイントがない場合、--rerank を指定しても効果はありません。
export INDEXIO_RERANK_BASE=http://rerank.internal.example:8081
export INDEXIO_RERANK_MODEL=Qwen/Qwen3-Reranker-8B
export INDEXIO_RERANK_KEY=...
インデックスに登録されないもの
- コード、ドキュメント、設定、スクリプト、データのいずれかとして認識される拡張子を持たないファイル。データベース、画像、アーカイブ、コンパイル済みの出力などが該当します。
- バイナリコンテンツ:先頭 8 KiB に NUL バイトが含まれているファイルはスキップされます。4 MiB を超えるファイルと、256 KiB を超えるテキストファイルも対象外です。通常のフォルダーでは、これらのファイルとドキュメント(PDF、Office)は名前のみがインデックスに登録されます(ソースの追加を参照)。
- ビルド出力、依存関係、キャッシュのフォルダー(
node_modules、target、dist、vendor、CACHEDIR.TAGを含むフォルダー)、git で無視されるファイル、設定用のフォルダー(.github、.cargo、.vscode、.devcontainer…)を除く隠しフォルダー、ロックファイル、圧縮済みファイル、ソースマップファイル。 - 認証情報:
.envファイル、秘密鍵と証明書(pem、key、p12、pfx、jks、gpg…)、.netrc、.npmrc、Terraform の状態ファイル。以前のバージョンでインデックスに登録された認証情報ファイルは、次回の同期時に削除されます。.env.exampleと*.pubは保持されます。
recall が検索するセッションのトランスクリプトと実行ログは、保存前に機密情報がマスキングされます。秘密情報に見える設定値、URL 内のパスワード、API キー、ベアラートークン、JWT、秘密鍵ブロックは <redacted> に置き換えられます。
HTTP API のセキュリティ保護
indexio serve は、デフォルトでループバックアドレスにバインドします。
indexio serve --auth-token $(openssl rand -hex 32) # one bearer token
トークンごとにリポジトリへのアクセスを設定するには、ACL ファイルを使用します。
cat > acl.json <<'EOF'
{"tokens":{"indexio-reader":{"allow":["team-*","core"]},"indexio-admin":{"allow":["*"]}}}
EOF
indexio serve --acl-file acl.json
ACL ファイルを使用すると、次のようになります。
- 未知のトークンには HTTP 401 が返されます。
- 許可されたパターンに一致しない検索結果は、
/search、/symbol、/callsから除外されます。 - 管理者用ルートには、
allow: ["*"]を持つトークンが必要です。それ以外のトークンには HTTP 403 が返されます。 GET /healthは常に公開されています。
注意。 ループバック以外のバインドアドレス(--bind 0.0.0.0)は、--auth-token、$INDEXIO_AUTH_TOKEN、または --acl-file も設定しない限り拒否されます。stdio 経由の MCP サーバーはローカルユーザーとして実行され、設計上、認証機能はありません。ネットワークに公開する MCP サーバーは、ご自身のゲートウェイの背後に配置してください。
チームでのインデックス作成:ワークツリーのライブオーバーレイ
indexio serve は、各開発者の未コミットの変更を共有インデックスに重ねて表示できます。そのため、エージェントが あなた に回答する際は、あなた の作業ツリー(編集内容、未追跡ファイル、削除)を参照し、ほかの全員にはプッシュ済みの状態が表示されます。開発者のマシンに必要なのは、エージェントハーネス内のシェルフックだけです。indexio クライアントをインストールする必要はありません。
仕組み
- サーバーがプッシュ済みのリポジトリをインデックスに登録します(通常の
add+sync)。 - エージェントハーネスの
PreToolUseフックが、indexio のツール呼び出しのたびにintegrations/claude-code/indexio-team-sync.shを実行します。このスクリプトは、リモートのデフォルトブランチとのマージベースを基準に作業ツリーの差分(未追跡ファイルを含む)を取得し、パッチを/team/worktreeに POST します。 - サーバーは、呼び出し元のユーザー名をキーにした小さなオーバーレイシャードにパッチを適用し、ベースシャードに重ねます。変更されたパスはベースインデックスを上書きし、削除されたパスは非表示になり、それ以外はすべて共有インデックスから読み取られます。適用にはスクラッチインデックス上で git plumbing を使用するため、チェックアウトやワークツリーは作成されません。
- 最後に受け付けたパッチのハッシュがディスクに保存されるため、変更のない状態で呼び出しを繰り返してもコストはかかりません。フックは何も出力せず、常に 0 で終了するため、ツール呼び出しを妨げたり、エージェントのコンテキストを汚染したりすることはありません。
オーバーレイは更新がない状態で INDEXIO_TEAM_TTL_DAYS(デフォルトは 7 日)を過ぎると有効期限が切れます。
サーバーのセットアップ
"user" を含むトークンを持つ ACL ファイルを使ってサーバーを実行します。この名前がオーバーレイのキーになります。
cat > acl.json <<'EOF'
{"tokens":{
"tok-alice":{"allow":["*"],"user":"alice"},
"tok-bob": {"allow":["*"],"user":"bob"},
"tok-ci": {"allow":["*"]}
}}
EOF
indexio serve --acl-file acl.json --bind 0.0.0.0
"user" を持たないトークンでも読み取りには使えますが、オーバーレイはありません(上記の CI を参照)。ACL ファイルの代わりに単一の --auth-token を使用する場合、クライアントは X-Indexio-User ヘッダーでユーザーを指定します。
開発者のセットアップ
indexio setup claude --team-sync # writes the hook script, prints the entry
export INDEXIO_URL=https://indexio.example.com
export INDEXIO_TOKEN=tok-alice
setup claude --team-sync はフックスクリプトを Claude の設定ディレクトリに書き込み、settings.json 用の PreToolUse エントリを表示します。マッチャーは mcp__indexio__.* なので、同期は indexio ツール呼び出しの直前に実行されます。ユーザーごとのトークンではなく共有トークンを使う場合は、操作対象のユーザー名を INDEXIO_USER にも設定してください。
サーバー側で強制される制約
- 認証情報のパス(
Lang::is_secret_path)はオーバーレイに受け付けられず、32 MiB を超えるパッチも受け付けられません。 - ACL の
allowパターンで、各ユーザーが読み取れる内容を絞り込みます。MCP ではドキュメント自体に適用します(レンダリング済みテキストを後から非表示にはできません)。REST API ではヒットをフィルタリングします。 - オーバーレイのユーザー名は
[A-Za-z0-9._@-]に制限され、先頭にドットは使えません。これにより、オーバーレイの状態をパスセーフに保ちます(SSO ID は通常メールアドレスです)。
多数の開発者に同時にサービスを提供する
sync、reindex、またはコンパクションによって新しいシャードが書き込まれると、サーバーはインデックスを自動的に再オープンします。新しいエンジンはリクエスト処理の外でオープンされ、ウォームアップされた後に切り替わるため、誰かが/admin/reloadを呼び出す必要はなく、リクエストが待たされることもありません。セマンティックプレーンは起動時と各埋め込み処理の後に解析されます。- すべてのリクエストはワーカープールで実行され、小規模な検索は共有の並列プールを使いません。そのため、ほかのユーザーが広範囲な grep やハイブリッド検索を行っていても、
find_symbolやread_spanは約 1 ミリ秒で応答します。 - 開発者ごとのビューは、共有インデックスにその開発者のオーバーレイを重ねたものです。開発者 1 人あたり約 1 MB で、数ミリ秒でオープンでき、アップロードのたびに直後からバックグラウンドでオープンされます。
- 全員で 1 つのコンテンツキャッシュを使用します。
INDEXIO_CONTENT_CACHE_MB(デフォルトは 1024)は、すべてのユーザーの検索で使われる展開済みファイルを保持します。 - 圧縮を受け付けるクライアントには、レスポンスを gzip で圧縮して送信します。フックは大きなパッチを gzip で圧縮してアップロードします。
- ローカルセッションと同様に、セッション自身のリポジトリを検索結果で優先し、
read_spanとfile_outlineのデフォルトにします。クライアントがX-Indexio-Repoヘッダーで指定したリポジトリ(名前または origin URL)が対象です。指定がない場合は、開発者が最後に編集内容を同期したリポジトリが対象になります。 diffを指定せずに実行したimpact_of_diffは、開発者が同期した作業ツリーとそのマージベースを比較します。
制限事項
- オーバーレイは字句プレーンです。ベクトル検索ではベースのコンテンツを順位付けします。追跡対象ファイルへの編集内容はすべてのツールに反映され、新規の未追跡ファイルと削除は字句、シンボル、アウトラインの各ツールで確認できます。
- ベースはサーバーに存在するコミットである必要があります(
origin/HEADとのマージベース、なければorigin/main、origin/master、または上流ブランチ)。そうでない場合、アップロードは HTTP 409 で拒否され、次回の呼び出し時に再試行されます。サーバーは origin を自動的にフェッチします。頻度は 1 分に 1 回までです。 - フックは Claude Code 向けに調整されています。他のハーネスも
PreToolUseコントラクトに収束しつつありますが、テスト済みなのは Claude Code のみです。
エンタープライズ向けセットアップ
上記のすべては 1 台のマシンで動作します。同じバイナリをチームサーバーや組織全体のデプロイに拡張できます。必要な変更点は、ネットワークの境界と認証です。
ネットワーク内(LAN / VPN)
最もシンプルな構成は、内部ホスト上の indexio サーバー 1 台をプライベートインターフェースにバインドする方法です。信頼できるネットワークでは TLS は任意です。
indexio serve --bind 10.0.0.5 --acl-file acl.json
開発者は INDEXIO_URL と INDEXIO_TOKEN を使って、チーム同期フックの接続先を設定します。まず ACL ファイルから始め、トークンの配布が手間になったら SSO(後述)に移行してください。
インターネットに公開する場合
サーバーはプレーンな HTTP を使用し、認証情報なしで広範囲にバインドすることを拒否するため、TLS を終端してループバックポートに転送するリバースプロキシの背後に配置してください。最小限の Caddy サイト設定は次のとおりです。
indexio.example.com {
reverse_proxy 127.0.0.1:7717
}
次に、静的トークンではなく SSO でサービスを提供します。短期間有効な ID トークンは、ノート PC 上の長期間有効なベアラートークンより安全です。
OIDC プロバイダー(Entra ID、Google、Keycloak)による SSO
--oidc-issuer + --oidc-audience は、静的トークン方式に代わるものです。サーバーは
<issuer>/.well-known/openid-configuration でプロバイダーを検出し、JWKS を
キャッシュします。また、ID を検索する前に、すべてのベアラートークンを検証します(RS256、issuer、audience、有効期限)。検証に失敗した場合は拒否します:
cat > users.json <<'EOF'
{"users":{
"[email protected]":{"allow":["*"],"user":"alice"},
"[email protected]":{"allow":["payments-*"]}
}}
EOF
indexio serve \
--oidc-issuer https://login.microsoftonline.com/<tenant-id>/v2.0 \
--oidc-audience <application-id-uri> \
--acl-file users.json --bind 0.0.0.0
- ID にはトークンの
emailクレーム(ない場合はsub)が使われます。users.jsonに存在しない ID には HTTP 401 が返されます。プロビジョニングには既存のディレクトリを使用し、手動または同期ジョブでこのファイルに反映してください。 allowはトークン ACL とまったく同じように機能します。/adminには引き続き*が必要です。"user"はチームオーバーレイ名を設定します。指定しない場合はメールアドレスが使われます。- IdP 固有の設定。Entra ID:公開された API を持つアプリ登録を作成し、audience には Application ID URI を指定します。Google Workspace:ウェブアプリケーションの OAuth クライアントを作成し、audience にはクライアント ID を指定します。Keycloak:レルム内に機密クライアントを作成し、audience にはクライアント ID、issuer には
https://<host>/realms/<realm>を指定します。 - 署名キーは再起動なしでローテーションされます。不明な
kidがある場合は、必要に応じて JWKS を再取得します。 - OIDC モードは
--auth-token/INDEXIO_AUTH_TOKENより優先されます。これらは未設定のままにしてください。--oidc-audienceを指定するには、--oidc-issuerが必要です。
試してみる:Google Workspace を 10 分で設定
2026-09-27 に稼働中のサーバーを使ってエンドツーエンドで検証した、具体的な手順です。
-
Google Cloud コンソールでプロジェクトを作成します(例:
indexio-pilot)。 -
API とサービス → OAuth 同意画面:外部を選択し、アプリ名に
indexio pilotを指定します。スコープにはopenidとemailを追加し、テストユーザーに自分の Google アカウントを追加します。アプリが「テスト」状態の間は、テストユーザーのみが同意できます。ここが忘れられがちな手順です。 -
認証情報 → OAuth クライアント ID を作成 → ウェブアプリケーション:認証済みのリダイレクト URI
https://developers.google.com/oauthplaygroundを追加します。 -
https://developers.google.com/oauthplayground で実際の ID トークンを発行します:歯車アイコン →「独自の OAuth 認証情報を使用」→ クライアント ID とシークレットを貼り付ける → スコープに
openid emailを指定 → API を承認 → 同意 → 認証コードをトークンと交換 →id_tokenをコピーします。 -
audience にクライアント ID を指定し、ユーザーファイルに自分のメールアドレスを追加してサーバーを起動します:
cat > users.json <<'EOF' {"users":{"[email protected]":{"allow":["*"],"user":"pilot-you"}}} EOF indexio serve --bind 0.0.0.0 \ --oidc-issuer https://accounts.google.com \ --oidc-audience <client-id>.apps.googleusercontent.com \ --acl-file users.json -
任意の場所からスモークテストを実行します:
curl -H "Authorization: Bearer $ID_TOKEN" http://indexio.example.com:7717/search?q=parse # 200 with the token; 401 without. The token lives one hour — re-run # the playground exchange for a fresh one.
OAuth 同意フローを実行できるものであれば、OAuth Playground 以外でもサーバーが受け付けるベアラートークンを発行できます。IDE プラグイン、サーバーの前段に置く小さなログインページ、CI ジョブなどが該当します。
GitHub
GitHub は独自 API 向けの汎用 OIDC プロバイダーではありませんが、次の 2 つの方法があります:
-
GitHub Actions → indexio はすでに OIDC に対応しています。
permissions: id-token: writeを指定したジョブは JWT(issuer はhttps://token.actions.githubusercontent.com、audience は任意)を要求し、ベアラートークンとして indexio クライアントに渡せます。サーバーは他の OIDC トークンと同様に検証します:indexio serve --oidc-issuer https://token.actions.githubusercontent.com \ --oidc-audience indexio --acl-file users.jsonCI マシンに静的トークンを保持する必要はありません。また、
users.jsonの許可リストで各ワークフローが読み取れる範囲を制限できます。 -
GitHub アカウントを持つ人間の場合。 GitHub 用に設定した OIDC ゲートウェイ(oauth2-proxy)を前段に配置し、ゲートウェイと indexio の間では ACL ファイルのトークンを使用します。または、ディレクトリに基づくプロビジョニングに適した Entra ID/Google に人間のアクセスを移行します。
人間とエージェント
2 つの利用者グループには異なる認証情報を使用してください。人間には有効期間の短い SSO トークンを、エージェントと CI にはアクセスするリポジトリに範囲を限定した ACL ファイルのトークン(allow: ["payments-*"])を使用します。人間のアクセスを取り消すにはディレクトリアカウントを無効化し、エージェントのアクセスを取り消すには ACL ファイルから該当する行を削除します。
indexio を Claude Code で使用する
indexio は stdio 経由で MCP を使用します。これは Claude Code、Claude Agent SDK、およびほとんどのコーディングエージェントのネイティブなツールインターフェイスです。
サーバーを登録する
次のいずれかを実行します。
-
indexio setup claudeを実行します。バイナリとデータディレクトリに対してclaude mcp addを実行し、CLAUDE.md用の案内ブロックを表示します。ブロックを追記するには、--claude-md ~/.claude/CLAUDE.mdを追加します。 -
claude mcp add indexio -- /usr/local/bin/indexio mcp --data-dir /var/lib/ciindexを実行します。 -
.mcp.jsonをプロジェクトにコミットします。{ "mcpServers": { "indexio": { "command": "/usr/local/bin/indexio", "args": ["mcp", "--data-dir", "/var/lib/ciindex"] } } }
フックをインストールする
indexio hook install
これにより、Claude Code の5つのフックが ~/.claude/settings.json に書き込まれます。
| フック | 効果 |
|---|---|
| PreToolUse, Bash | インデックス登録されたファイルのシェルによる読み取りや検索(cat、sed -n、head、grep、rg、find、ファイルを開くだけの python -c または node -e のワンライナー)は拒否されます。拒否メッセージには、同じ結果を得られる indexio の呼び出しが示されます。たとえばスクリプトやビルドなど、ほかの処理も行うコマンドは入力どおりに実行されます。 |
| PreToolUse, Read | 60行を超えるインデックス登録済みファイル全体の Read は拒否されます。拒否メッセージには file_outline と read_span が示されます。エージェントのワークツリーにある、インデックス登録済みファイルと同一のコピーを Read した場合も、そのファイルの読み取りとして扱われます。 |
| PreToolUse, PowerShell | Get-Content、Select-String、Get-ChildItem | Select-String による読み取りと検索にも同じルールが適用されます。これには、$c = Get-Content f の後に行範囲やループを使う場合も含まれます。 |
| PreCompact | セッションのトランスクリプトと Claude Code のメモリーノート(~/.claude/projects/*/memory/)が recall ツール用にインポートされます。 |
| SessionStart | 新しいセッションには、同じプロジェクトの前回のセッションに関する1行の情報が渡されます。内容は、タイトル、日付、変更されたファイル、コミット、およびそのカードの recall 呼び出しです(70~115トークン)。圧縮後は、そのセッションで変更されたファイルとコミットがセッションに返されます(75~300トークン)。再開されたセッションには何も渡されません。 |
Bash フックは、スクリプトやビルド(python、node、npm、pytest、go、
make …)も indexio run 経由で実行します。これにより、長い出力がコンテキストに入らないようにできます。最初の行、エラー行、最後の行が runs:<repo>/<log> のポインターとともに返され、出力全体は30日間検索可能な状態で保持されます。
拒否されたコマンドを入力どおりに実行するには、コマンドに # raw を追加して再送信するか、
INDEXIO_RAW=1 を設定します。
ツール
| ツール | 用途 |
|---|---|
code_search | リテラル検索または正規表現検索(mode: "lexical")、概念検索("semantic")、またはその両方("hybrid")。grep パターンのような語句を指定した字句検索で一致がない場合は、正規表現として実行されます。複数の単語を指定した字句検索で一致がない場合は、ハイブリッド検索として実行されます。 |
code_grep | すべてのリポジトリを対象にした grep -n:ファイルごとに一致する行をすべて表示し、順位付けします。repo および path 引数、または末尾の repo:、path:、lang: フィルターを使用できます。対応しない括弧はリテラルとして扱われます。 |
find_symbol | 関数、構造体、クラス、トレイト、列挙型の定義場所を検索します。 |
who_calls | シンボルを呼び出すすべての記録済みの呼び出し元を検索します。 |
semantic_search | ベクトル検索のみを実行します。 |
list_files | インデックス化されたパスを対象に、ディレクトリごとにまとめた glob または部分文字列検索を行います。パターンを指定しない場合は、すべてのファイルを表示します。 |
file_outline | ファイル内のすべての定義と開始・終了行、または Markdown ファイルの見出しを表示します。ファイル全体の代わりに数百トークンで確認できます。mod tests または Test… クラスのテストは、名前と開始行を含む1行で表示されます。 |
read_span | インデックス化されたファイルの指定した行範囲を正確に読み取ります。終了行を指定しない場合は、開始行にある定義全体を読み取ります。 |
impact_of_symbol | すべてのリポジトリにわたる、シンボルの推移的な呼び出し元を検索します。 |
impact_of_diff | パッチまたは未コミットの作業ツリーによって影響を受ける、呼び出し元とインポート元を検索します。 |
refresh_index | セッション内から差分の再インデックス化、埋め込み、再読み込みを行います。 |
recall | 過去のセッション、Claude Code のメモリノート、保存済みのコマンド出力(依頼、回答、ツール呼び出し、結果、ビルドおよびテストログ)を検索します。一致が1件の場合は、そのやり取りも表示されます。brief: true を指定すると、代わりにセッションカードを返します。各セッション約1,000トークンで、依頼、変更したファイル、コミット、結果が含まれます。query: "" を指定すると、このプロジェクトの最新セッションが表示されます。 |
index_stats | インデックス化されている内容、最新の状態かどうか、および組み込みツールの過去1週間の使用状況を表示します。 |
サーバーは Claude に対し、各 indexio ツールがどの組み込みツールの代わりとなるか、およびどのリポジトリがインデックス化されているかを伝えます。その後、Claude は識別子を字句検索に、質問をハイブリッド検索に自動で振り分けます。ファイル全体ではなく、アウトラインと範囲を指定してファイルを読み取ります。
結果は情報密度の高いプレーンテキストです。repo:path と line: snippet の行でグループ化され、ファイル一覧はまとめられ、範囲には番号が付けられます。スコア、順位、JSON の句読点は含まれません。同じ検索結果の場合、コンパクトな JSON と比べてトークンを54%削減できます。JSON 形式を使用するには、INDEXIO_MCP_FORMAT=json を設定してください。
トークン削減量の実測
同じタスクで組み込みツールと比較
bench/ab_readme.py は、同じリポジトリを対象に、コーディングエージェントが行うタスクを Claude Code の組み込みツールと indexio で実行します。Grep は一致するすべての項目を path:line:text 形式で出力します。Read はファイル全体を出力し、上限は2,000行です。Glob は1行につき1つのパスを出力します。トークン数の計測には tiktoken を使用します。実際の3つのリポジトリを使用し、インデックスには44のリポジトリが含まれます。各リポジトリから10個のシンボルと3種類のファイルを対象に、モデルが質問を作成します。
| タスク | 組み込み | indexio | 変化 |
|---|---|---|---|
| シンボルの定義場所を探す(30) | 814 | 1,421 | 悪化。find_symbol はすべてのリポジトリを一覧表示します。対象を絞った grep なら1つだけ見つかります。 |
| シンボルの呼び出し箇所を一覧表示する(30) | 2,018 | 1,409 | −30% |
| 関数を1つ読み取る(ファイルは判明、行は不明)(30) | 419,380 | 41,612 | −90% |
| 特定の種類のファイルを一覧表示する(9) | 12,216 | 3,887 | −68% |
| コードについての質問に答える(11) | 1,144,842 | 1,883 | −99.8% |
| すべてのタスク | 1,579,270 | 50,212 | −97% |
組み込みツールのほうが少ないトークンで済む場合、その差は数百トークンです。一方、コストが高い場合は桁違いに大きくなります。これは、Read がファイルを返し、Grep がすべての単語の一致箇所をすべて返すためです。
実際のトラフィックで
サーバーは、返したバイト数とともにすべての呼び出しをログに記録します。組み込みツールに機械的な相当機能がある場合、サーバーはそのツールが返すはずの内容もログに記録します。
| 呼び出し | 組み込みの相当機能 |
|---|---|
read_span | ファイル全体に対する Read。ファイルのバージョンごとに1回課金され、ファイルが変更された後は再度課金されます |
find_symbol、who_calls、code_grep、字句ベースの code_search | セッションのリポジトリでの Grep。先頭250行 |
list_files | 絶対パスを返す Glob |
file_outline | なし。コストとして計上されます |
ハイブリッド検索、recall、影響分析ツール | なし。比較対象外です |
index_stats は、すべてのセッションを対象とした直近7日間の集計を出力します。indexio usage は、ツール別およびリポジトリ別に同じ情報を出力します。著者のマシンで実際のコーディングセッションを1日行った結果は、比較対象の呼び出しが423件、組み込みツールなら596kトークンを返すところ、提供されたのは220kトークンで、63%の削減となりました。read_span だけでは71%削減されました。
影響分析
indexio impact --symbol RateLimiter::acquire --depth 2 # transitive callers, all repositories
indexio impact --diff my-service # uncommitted working-tree changes
indexio impact --diff-file pr.patch --repo my-service # a patch
indexio impact --file my-service:src/auth/token.rs # every definition in a file, plus importers
indexio outline my-service:src/auth/token.rs # definitions with line ranges
indexio span my-service:src/auth/token.rs 120:160 # exact lines
この探索は、インデックスが保持する逆呼び出しグラフに対する幅優先探索です。インデックス作成時のコストはなく、ミリ秒単位で結果が得られます。パッチは、変更されたファイルだけを対象とする tree-sitter の処理によって定義に対応付けられます。変更されたファイルは結果から除外されます。そのファイルをインポートしている箇所は、言語を考慮したインポートクエリで見つけます。
エッジは名前に基づいています。Foo::new と Bar::new は、new という同じノードを共有します。各呼び出し箇所には caller、path、symbol が含まれるため、エージェントはこれらを使って絞り込めます。ファンアウトの上限によってハブとなる名前の範囲が制限され、上限に達した場合は truncated: true で通知されます。
HTTP API も同じインターフェースを提供します。GET /impact/symbol、POST /impact/diff、GET /outline、GET /span のいずれも ACL を適用します。
他のツールから indexio を使う
どのエージェントフレームワークからでも HTTP API を利用できます。
curl 'http://127.0.0.1:7717/search?q=auth%20token%20refresh&mode=hybrid&limit=10'
curl 'http://127.0.0.1:7717/symbol/RateLimiter'
curl 'http://127.0.0.1:7717/calls/RateLimiter::acquire'
応答は、リポジトリ、パス、行、列、スニペット、スコアを含むヒットの JSON リストです。
コマンドリファレンス
各コマンドは --data-dir DIR を受け付けます。デフォルトは $INDEXIO_DATA_DIR、次に ~/.indexio です。
コードのインデックス作成
indexio add ~/code # every git repository under a folder
indexio add ~/notes # a folder without git: indexed as-is
indexio add github:my-org # a GitHub organization
indexio add github:my-org/payments # one repository
indexio add azdo:my-org/Platform # an Azure DevOps project
indexio add https://gitlab.example.com/g/r.git
indexio add github:my-org --limit 20 --no-embed # trial run: 20 repositories, lexical only
indexio add github:my-org --dest /srv/clones # where remote clones go
indexio index ~/code/one-repo --name one # one repository, no source bookkeeping
indexio sources # sources and registered repositories
indexio remove github:my-org # forget a source
最新の状態を保つ
indexio sync # pull, discover, delta re-index, embed. Run from cron.
indexio sync --no-embed # lexical plane only
indexio reindex --repo payments # one repository, from HEAD
indexio reindex --repo payments --worktree # from the working tree, uncommitted edits included
indexio reindex --all
検索
indexio search parse_config # exact identifier
indexio search 'parse_config repo:payments lang:rust' # filters: repo: lang: path: case:
indexio search '"token refresh"' # phrase
indexio search '/fn (parse|load)_config\(/' # regex
indexio search 'how is backpressure applied' --mode hybrid # question
indexio search 'retry with exponential backoff' --mode semantic --limit 10
indexio search 'rate limiter' --mode hybrid --fusion combmnz # alternative fusion
indexio search 'rate limiter' --mode hybrid --rerank # needs INDEXIO_RERANK_BASE
indexio search parse_config --json
シンボルと影響範囲
indexio symbol parse_config # definitions
indexio calls parse_config # call sites
indexio impact --symbol parse_config # transitive callers and importers, 2 hops
indexio impact --symbol parse_config --depth 3 --max-sites 1000
indexio impact --diff payments # the uncommitted working tree
indexio impact --diff payments --base origin/main
git diff main | indexio impact --diff-file - --repo payments
indexio impact --file payments:src/config.rs
indexio impact --symbol parse_config --json
インデックスから読み取る
indexio outline payments:src/config.rs # definitions with start and end lines
indexio span payments:src/config.rs 120 # the definition at line 120
indexio span payments:src/config.rs 120:160 # a range, 400 lines at most
埋め込み
indexio embed # embed every repository, incrementally
indexio embed --repo payments
indexio embed --all --rebuild-model # retrain the built-in model from scratch
indexio embed --max-chars 800 # smaller chunks
indexio embcas-stats # embedding cache statistics
indexio embcas-stats --coverage # per repository: indexed files without vectors
サービスを提供する
indexio mcp # MCP over stdio
indexio mcp --repo payments # pin the session's repository
indexio serve # HTTP on 127.0.0.1:7717
indexio serve --port 8080 --auth-token $(openssl rand -hex 32)
indexio serve --bind 0.0.0.0 --auth-token "$TOKEN" # beyond localhost: a token is mandatory
indexio serve --acl-file acl.json
indexio serve --oidc-issuer https://idp.example.com --oidc-audience indexio-api --acl-file users.json
# team worktree overlays: POST /team/worktree (see "Team indexing" above)
エージェントのセットアップ
indexio setup claude
indexio setup claude --claude-md ~/.claude/CLAUDE.md
indexio setup claude --team-sync # also install the team worktree-sync hook
indexio hook install
indexio hook install --print-only
indexio sessions # import Claude Code transcripts for recall
indexio sessions --project C--Users-me-code-payments
コンテキストを埋め尽くさずにコマンドを実行する
indexio run -- python scripts/probe.py --fast # short output printed as is; long output stored + digested
indexio run -- npm test # the Bash hook does this rewrite for you
indexio run --cwd ~/code/payments -- pytest -q
保存されたログの形式は runs:<repo>/<stamp>-<command>.log です。要約から漏れた行は read_span で読み取り、recall で後から見つけられます。ログは INDEXIO_RETAIN_DAYS 日後に削除されます。
測定とメンテナンス
indexio stats # repositories, files, shards, index size
indexio usage # last 7 days of MCP calls, against the built-in tools
indexio usage --days 1 --json
indexio compact # merge shards
indexio compact --vectors # also merge vector segments
indexio cas-stats
環境変数
| 変数 | 効果 |
|---|---|
INDEXIO_DATA_DIR | データディレクトリです。デフォルトは ~/.indexio です。 |
INDEXIO_REPO | MCP セッションが操作するリポジトリです。デフォルトは、作業ディレクトリを含むリポジトリです。 |
INDEXIO_BIND | serve のバインドアドレスです。ループバック以外の場合は、トークンまたは ACL が必要です。 |
INDEXIO_AUTH_TOKEN | serve のベアラートークンです。 |
INDEXIO_TEAM_TTL_DAYS | 更新されない場合に、チームのワークツリーオーバーレイを保持する日数です。デフォルトは 7 日です。 |
INDEXIO_CONTENT_CACHE_MB | serve の展開済みコンテンツキャッシュです。全ユーザーで共有されます。デフォルトは 1024 です。 |
INDEXIO_URL、INDEXIO_TOKEN、INDEXIO_USER | チーム同期フックのサーバー、ベアラートークン、操作対象のユーザーです(共有トークンの場合のみ)。 |
INDEXIO_EMBED_BASE、INDEXIO_EMBED_MODEL、INDEXIO_EMBED_DIM、INDEXIO_EMBED_KEY | OpenAI 互換の埋め込みエンドポイントです。 |
INDEXIO_RERANK_BASE、INDEXIO_RERANK_MODEL、INDEXIO_RERANK_KEY | 再ランキングエンドポイントです。 |
GITHUB_TOKEN または GH_TOKEN、AZDO_TOKEN | リモートソースの認証情報です。ディスクには書き込まれません。 |
INDEXIO_MCP_FORMAT | ツールの結果形式です。text(デフォルト)または json を指定します。 |
INDEXIO_FUSE_WEIGHTS | ハイブリッド検索の各要素の重み lex,bm25,sem です。デフォルトは 0.5,1.0,0.3 です。 |
INDEXIO_EXPAND | シソーラスによるクエリ拡張を有効にします。デフォルトでは無効です。測定結果が悪化したためです。 |
INDEXIO_RETAIN_DAYS | 実行ログとレンダリング済みセッション記録を保持する日数です。デフォルトは 30 日です。0 を指定するとすべて保持されます。 |
INDEXIO_NO_USAGE | 使用状況ログを書き込みません。ベンチマーク用です。 |
INDEXIO_NO_AUTO_ADD | セッションによる、未登録のチェックアウトのインデックスへの追加を無効にします。 |
INDEXIO_RAW | フックされた Bash コマンドを、入力されたとおりに実行します。 |
INDEXIO_HOOK_DEBUG | Bash フックが判断内容を stderr に出力します。 |
Docker でデプロイする
リリースワークフローでは、linux/amd64 と
linux/arm64 向けに ghcr.io/ioserviceslabs/indexio を公開しています。イメージは非特権ユーザーとして実行されます。データディレクトリは /data です。
git と CA 証明書が含まれています。
自分のマシンを自分のエージェント用にインデックス化する場合は、代わりにバイナリをインストールしてください。 コンテナは、複数の人やマシンが HTTP 経由で検索する共有インデックス用です。自分のノート PC では、Bash フック、作業ツリーの即時更新、パス変換レイヤーが使えなくなる一方で、利点はありません。インストールを使用してください。このセクションの残りは、共有環境での使用と、何もインストールせずに indexio を試す場合を対象としています。
Docker 以外に何もインストールせず、このマシン上のフォルダーをインデックス化して検索します。
docker run --rm -v indexio-data:/data -v ~/code:/repos:ro ghcr.io/ioserviceslabs/indexio add /repos
docker run --rm -v indexio-data:/data ghcr.io/ioserviceslabs/indexio search parse_config
docker run --rm -v indexio-data:/data ghcr.io/ioserviceslabs/indexio stats
HTTP API を提供します。
docker run -d --name indexio -p 127.0.0.1:7717:7717 -v indexio-data:/data -e INDEXIO_AUTH_TOKEN="$(openssl rand -hex 32)" ghcr.io/ioserviceslabs/indexio
curl -H "Authorization: Bearer $TOKEN" 'http://127.0.0.1:7717/search?q=parse_config'
コンテナをエージェントの MCP サーバーとして渡します(docker run -i 経由の stdio)。
claude mcp add indexio -- docker run -i --rm -v indexio-data:/data -v ~/code:/repos:ro ghcr.io/ioserviceslabs/indexio mcp
コンテナがマシン上のコードをインデックス化する方法
コンテナは、バインドマウントした範囲を除き、ディスクにアクセスできません。2つのマウントがその役割を果たしますが、同じものではありません。
| マウント | 用途 | 必要なアクセス権 |
|---|---|---|
-v ~/code:/repos:ro | インデックス化するコードです。任意のものをマウントできます。1つのリポジトリ、チェックアウトのルート、複数の -v フラグなどです。 | 読み取り専用で十分です。インデックス化によってソースに書き込むことはありません。 |
-v indexio-data:/data | インデックス本体です。 | 書き込み可能である必要があります。これはDockerボリュームであり、ホスト上のフォルダーではありません。 |
indexio add /repos はマウント内をたどり、あらゆる階層にあるすべてのgitリポジトリを登録して、それぞれをインデックス化します。gitリポジトリを含まないフォルダーは、通常のツリーとしてインデックス化されます。各リポジトリは、コンテナから見たパスを使って /data/repos/<name>.json に記録されます。たとえば /repos/my-service であり、C:\Users\you\code\my-service ではありません。検索結果はリポジトリ相対パス(my-service:src/main.rs)なので、検索には影響しませんが、ホストのパスはインデックス内のどこにも記録されません。
大規模なインデックスを構築する前に知っておくべき重要な点が3つあります。
- コンテナのインデックスとホストのインデックスは、互換性がありません。 ホストのバイナリからコンテナ内で構築したデータディレクトリを指定すると、記録されている
/repos/...パスがホスト上に存在しないため、再インデックス化や、未インデックス化コンテンツに対するread_spanは失敗します。どちらか一方を選んで使い続けるか、データディレクトリを2つ用意してください。 - 最新状態を保つのはファイルウォッチャーではなく、同期ループです。 ローカルフォルダー上で
indexio syncを実行すると、ルート配下のリポジトリを再検出し、その時点でディスク上にある内容との差分を再インデックス化します。ソースのクローン、プル、書き込みは行いません。取得を行うのはリモートソースの種類(github:、azdo:、git URL)のみです。docker-compose.ymlのsyncサービスは15分ごとにこれを実行します。 - 自動更新はマウントを越えて機能しません。 通常、
indexio mcpは現在のリポジトリを監視し、編集後約25 msで作業ツリーを再インデックス化します。WindowsやmacOSホストのDocker Desktopバインドマウントでは、ファイルシステムイベントが確実に伝わらないため、コンテナ内では、インデックスは最後の入力時点ではなく、最後にsyncまたはrefresh_indexを呼び出した時点の状態だと考えてください。コードを編集するエージェントのそばでホストのバイナリを実行する主な理由はこれです。
Bashフック(indexio hook install)にもホストのバイナリが必要です。フックはシェル内のコマンドを書き換えますが、コンテナからシェルは見えません。
Windowsでは、上記のbashコマンドではなく、PowerShellでサーブトークンを生成してください。
$bytes = New-Object byte[] 32
[System.Security.Cryptography.RandomNumberGenerator]::Fill($bytes)
$env:INDEXIO_AUTH_TOKEN = [System.BitConverter]::ToString($bytes).Replace('-','').ToLower()
イメージでは INDEXIO_BIND=0.0.0.0 が設定されているため、INDEXIO_AUTH_TOKEN または --acl-file がないと serve は起動しません。すべてのソースのインデックスを認証なしで公開することはできません。コンテナ内で INDEXIO_BIND=127.0.0.1 に設定して「解決」しようとしないでください。サービスはコンテナ自身のループバックにバインドされ、公開ポートから到達できなくなります。バインド先は 0.0.0.0 のままにし、トークンを設定して、公開先を 127.0.0.1:7717:7717 にすれば、自分のマシンからのみ接続できます。
1 つのフォルダーを継続的にインデックスする
コードが C:\codebuilds にあり、タイマーで再インデックスし、エージェントから MCP 経由でクエリしたいとします。この場合、認証トークンは必要ありません。このトークンは serve と HTTP API を保護するもので、この構成ではどちらも実行しないためです。
フォルダーを登録し、インデックスを一度作成します。add は /repos を永続的なソースとして記録するため、以降の同期ではここから再読み込みされます。
docker run --rm -v indexio-data:/data -v C:/codebuilds:/repos:ro `
ghcr.io/ioserviceslabs/indexio add /repos
次に、ループで再同期するコンテナーを起動したままにします。イメージのエントリーポイントはバイナリなので、シェルを使えるように上書きします。
docker run -d --name indexio-sync --restart unless-stopped `
-v indexio-data:/data -v C:/codebuilds:/repos:ro `
--entrypoint /bin/sh ghcr.io/ioserviceslabs/indexio `
-c "while true; do indexio sync || true; sleep 900; done"
エージェントを同じボリュームに接続します。MCP サーバーは stdio を使用するため、ポートもトークンも必要ありません。
claude mcp add indexio -- docker run -i --rm -v indexio-data:/data -v C:/codebuilds:/repos:ro ghcr.io/ioserviceslabs/indexio mcp
docker run --rm -v indexio-data:/data ghcr.io/ioserviceslabs/indexio stats を実行して確認します。C:\codebuilds の下にあるすべてのリポジトリが一覧表示されます。
マウントにはスラッシュ(C:/codebuilds)を使用し、Docker Desktop のファイル共有設定でドライブが共有されていることを確認してください。15 分間隔では長すぎる場合は sleep の値を小さくしてください。ただし、編集内容が反映されるのは次回の同期後です。編集のたびにインデックスへ反映したい場合は、代わりにホスト上でバイナリを実行してください。
同じ設定を docker-compose.yml で行うには、フォルダーを指定し、同期サービスだけを起動します。
$env:INDEXIO_REPOS = "C:/codebuilds"
docker compose up -d sync
docker compose exec sync indexio add /repos
Compose はサービスを選択する前にファイル全体を展開するため、indexio サービスを起動しない場合でも、ファイルを解析できるよう INDEXIO_AUTH_TOKEN を設定する必要があります。上記のように設定するか、通常の docker run 形式を使用してください。
docker-compose.yml は、1 つのボリューム上で 2 つのサービスを実行します。
indexio:HTTP API を実行し、localhost でのみ公開します。sync:15 分ごとにindexio syncを実行します。GITHUB_TOKENとAZDO_TOKENは引き継がれます。
- インデックス対象のフォルダーを
./reposの下に配置します。 - サービスを起動します:
INDEXIO_AUTH_TOKEN=$(openssl rand -hex 32) docker compose up -d - フォルダーを一度インデックスします:
docker compose exec sync indexio add /repos
コンテナーは 0.0.0.0 にバインドします。バイナリは INDEXIO_AUTH_TOKEN または ACL ファイルがないと起動しません。docker build -t indexio . で、ソースから同じイメージをビルドできます。
アーキテクチャ
┌──────────────────────────── data dir ────────────────────────────┐
git repos │ shards/*.cidx immutable mmap'd index shards (single file) │
│ │ cas/ global content-addressed store (blake3 keyed) │
▼ │ embcas/ embedding CAS: (chunk-hash, model-id) → vector │
indexio-ingest │ vec/*.civec int8 vector segments + binary prescan │
git delta │ repos/*.json per-repo indexing state (last commit) │
│ └──────────────────────────────────────────────────────────────────┘
▼
Lexical plane Semantic plane
───────────────────── ──────────────────────────
trigram inverted index tree-sitter chunking
FST term dictionary, LEB128 postings pluggable embedder (built-in model
symbols + call edges (tree-sitter, or any OpenAI-compatible endpoint)
6 languages, AST discarded at once) embedding CAS (org-wide dedup)
query planner: required literals, mmap'd binary prescan + int8 rescore
galloping intersection, verify, BM25
└─── indexio-query: RRF fusion → optional reranker ───┘
│
CLI · HTTP (axum) · MCP (stdio JSON-RPC)
設計上の 5 つの判断:
- 常駐 AST ではなく、トライグラムインデックス。 indexio は AST を解析してシンボル、呼び出しエッジ、チャンク境界を取得し、その後 AST を破棄します。常駐 AST はテキストサイズの 20~50 倍の容量を必要とします。トライグラムシャードはコーパスの 1~3 倍の容量で、数ミリ秒で応答します。
- グローバルなコンテンツアドレス指定ストア。 抽出したアーティファクトと埋め込みは、組織全体でコンテンツハッシュをキーとして保存されます。フォーク、ベンダーコピー、重複ファイルは、それぞれ一度だけインデックス化および埋め込みされます。
- トゥームストーン付きの不変 mmap シャード。 インデックスのビルドでは新しいシャードが書き込まれます。削除はビットマップのトゥームストーンで記録されます。
indexio compactはバックグラウンドでシャードをマージします。読み取りによって書き込みがブロックされることはありません。 - Git ネイティブの差分インデックス化。 再インデックスでは HEAD ツリーの差分をたどります。変更されていない blob は再読み込み、再解析、再埋め込みされません。1 ファイルのコミットなら、1 秒未満で再インデックスされます。
- 独立したセマンティックプレーン。 ベクトルインデックスはストアとシャードから生成されます。字句インデックスに触れることなく、埋め込みモデルを変更したり、プレーンを再構築したりできます。
データレイアウト:
<data-dir>/
shards/*.cidx immutable index shards (mmap'd)
cas/v2/<hh>/<rest> content-addressed extracted artifacts (zstd)
embcas/<model>/ content-addressed embeddings, one pack per model
vec/<model>.*.civec int8 vector segments with a binary prescan
bm25/*.cibm25 chunk-level BM25 sidecar (mmap'd)
sem/*.rimodel the built-in semantic model (mmap'd)
repos/<name>.json per-repository state
sessions/ rendered session transcripts for recall (30-day window)
runs/<repo>/*.log command output kept by `indexio run` (30-day window)
usage/<day>.jsonl the MCP usage log
測定済みのパフォーマンス
作成者のマシンで、44 リポジトリ、10,000 ファイルのデータディレクトリを使用して測定したストレージ容量と起動時間(docs/SPEC-P10.md):
| 指標 | 変更前 | 変更後 |
|---|---|---|
| ソースコード 143 MB 分のデータディレクトリ | 5.3 GB | 1.0 GB |
| サーバー起動:時間、読み取りバイト数、RSS | 188 ms, 302 MB, 417 MB | 10 ms, 0 MB, 74 MB |
| ハイブリッドクエリ、プロセス起動済み | 130 to 190 ms | 7 to 14 ms |
| 正規表現の grep、プロセス起動済み | 424 ms | 28 ms |
find_symbol、who_calls | 12 ms | 0.5 ms |
| 編集後の作業ツリーの再インデックス | 利用不可 | 約 25 ms |
シェル経由とインデックス経由で同じ検索を実行した結果(bench/ab_speed.py。このリポジトリでは、1,300 ファイルの TypeScript アプリケーションでも同様の傾向が見られます)。実時間の中央値(10 回測定)。インデックス側には MCP トランスポートが含まれます。
| 検索 | シェル | indexio |
|---|---|---|
識別子の grep(rg -n) | 32 ms | 0.6 ms |
正規表現の grep(rg -n) | 34 ms | 2.5 ms |
アプリケーション全体の grep -rn | 26 to 860 ms | 0.7 ms |
120 行の読み取り(sed -n) | 23 ms | 0.3 ms |
find -name | 25 to 410 ms | 0.9 ms |
| 定義の検索 | 33 ms | 0.1 ms |
Bash ツールの呼び出しでは、コマンドの実行前にシェルの起動で約 15 ms、2 つの PreToolUse フックで約 30 ms もかかります。MCP 呼び出しでは、どちらも発生しません。実際のトラフィック(7 日間で 5,355 回の呼び出し)では、read_span の中央値は 0 ms、code_search は 12 ms、code_grep は 29 ms です。90 パーセンタイルも 130 ms 未満です。
サンドボックス(2 コア、RAM 4 GB)で測定した重複排除の結果:
| シナリオ | 結果 |
|---|---|
serde のインデックス作成後、同一内容のフォークを作成 | フォーク:キャッシュヒット率 100 %、10.0 s から 3.0 s に短縮 |
ripgrep のインデックス作成後、1 ファイルを変更したフォークを作成 | フォーク:キャッシュヒット率 100 %、6.6 s から 2.5 s に短縮 |
| 4 リポジトリの再埋め込み、19,977 チャンクインスタンス | 4,731 件の一意な埋め込み、76 % を重複排除 |
同じサンドボックスでの字句検索のレイテンシ:まれな識別子は 21 ms、一般的な用語は 81 ms、正規表現は 254 ms。1 ファイルのコミットの差分再インデックスは 792 ms です。
20 件の概念クエリで測定したセマンティック品質(bench/known_answers20.json、bench/eval_modes.py):
| モード | MRR | recall@5 |
|---|---|---|
| 字句検索 | 0.050 | 5 % |
| セマンティック検索 | 0.293 | 40 % |
| ハイブリッド | 0.397 | 60 % |
測定の結果、採用を見送ったもの:CombMNZ フュージョンは RRF を下回りました。オフラインのオーバーラップ再ランキングはハイブリッド単独を下回りました。シソーラスによるクエリ拡張は通常のセマンティック検索を下回りました。IVF プリスキャンでは速度が向上しませんでした。これらはデフォルトで無効です。
制限事項
- 型解決済みのクロスリファレンスはありません。 呼び出しエッジは名前ベースです。
new、get、runのようなオーバーロードされた名前ではノイズが発生します。callerとpathで絞り込んでください。 impact --diffでは未追跡ファイルは対象外です。git diffには含まれません。ステージするか、パッチを渡してください。- 組み込みモデルはニューラルモデルではありません。 実用的で低コストです。ニューラルモデルの品質が必要な場合は、
INDEXIO_EMBED_BASEを設定してください。 - MCP に認証機能はありません。 標準入出力を介して、ローカルユーザーとして実行されます。ゲートウェイなしでネットワークに公開しないでください。
- Web UI と分散クエリには対応していません。 バイナリ 1 つ、データディレクトリ 1 つです。
開発とリリース
cargo test --workspace # every crate, 325 tests
cargo clippy --workspace --all-targets
tools/build-release.sh # release build; remaps local paths out of the binary
クレート:indexio-types(共有型、ポスティングコーデック)、indexio-core(n-gram、検証、クエリリテラル)、indexio-index(シャード、マージ、トゥームストーン)、indexio-symbols(6 言語の tree-sitter シンボル、呼び出し、チャンク)、indexio-ingest(git 差分、コンテンツストア、ソース)、indexio-embed(エンベッダー、埋め込みストア、ベクトルインデックス、パイプライン)、indexio-query(プランナー、ランキング、融合、インパクト)、indexio(CLI、HTTP、MCP、フック)。設計に関するメモは docs/ にあり、docs/DEVELOPMENT.md は運用マニュアルです。
CI(.github/workflows/ci.yml)はプッシュとプルリクエストのたびに実行されます。マニフェストの解析、スクリプトのコンパイル、ワークフローの有効性を確認します。90 秒後に強制終了されます。ビルドとテストスイートはローカルで実行します。CI の制限時間内には収まりません。
リリース(.github/workflows/release.yml)は main から作成されます。
Cargo.toml([workspace.package])のversionを設定します。mainにマージします。90 秒以内にワークフローがv<version>タグと、生成されたリリースノートを含む GitHub リリースを作成します。バージョンを変更せずにマージした場合は何も行われません。- 同じワークフローで Linux(x86_64、aarch64)、macOS(Apple シリコン、Intel)、Windows(x86_64)向けのバイナリをビルドし、各アーカイブに
.sha256ファイルを付けてリリースに添付します。また、pip ホイールをリリースに添付し、コンテナイメージをghcr.ioに公開します。NPM_TOKENシークレットが存在する場合は npm パッケージを公開し、PYPI_API_TOKENシークレットが存在する場合はindexio-cliのホイールを PyPI に公開します。これらのジョブでは Rust をコンパイルするため、数分かかります。
tools/release-assets.sh は、ワークフローが対応していないプラットフォーム向けに、メンテナーのマシンから 1 つのアセットをビルドして添付します。
ライセンス
Apache License 2.0 です。LICENSE と NOTICE を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。