概要
チームで共有可能な設定ファイル commandindex.toml をリポジトリルートに配置し、インデックス設定やEmbeddingプロバイダー設定をチーム全体で統一できるようにする。
背景・動機
現在の設定は .commandindex/ 内に閉じており、.gitignore で除外されるためチーム共有ができない。チームで同じ設定(除外パターン、Embeddingモデル、検索デフォルト等)を使いたい場合に、各メンバーが個別に設定する必要がある。
提案する解決策
設定ファイルの優先順位
1. 環境変数 (COMMANDINDEX_*) ← 最優先(個人オーバーライド)
2. .commandindex/config.local.toml ← ローカル個人設定(.gitignore対象)
3. commandindex.toml ← リポジトリルート(チーム共有、Git管理)
4. .commandindex/config.toml ← 旧設定(deprecated fallback、警告付き)
5. デフォルト値 ← フォールバック
マージ仕様
- フィールドレベルマージ: 各設定フィールド単位で上位優先度の値が下位を上書きする(セクション単位ではない)
- 上位ソースで未指定(Option::None)のフィールドは、下位ソースの値を維持する
マージ例:
# commandindex.toml(チーム共有)
[embedding]
provider = "ollama"
model = "nomic-embed-text"
endpoint = "http://localhost:11434"
# .commandindex/config.local.toml(個人設定)
[embedding]
endpoint = "http://my-server:11434"
# → 有効設定: provider="ollama", model="nomic-embed-text", endpoint="http://my-server:11434"
環境変数オーバーライド
Phase 1 では以下の環境変数のみサポート(既存互換):
COMMANDINDEX_OPENAI_API_KEY: OpenAI APIキーの上書き
将来的に COMMANDINDEX_EMBEDDING_PROVIDER, COMMANDINDEX_EMBEDDING_MODEL 等の網羅的な環境変数対応は別Issueで対応予定。
設定ファイルフォーマット
# commandindex.toml(チーム共有)
[index]
# 対象言語の優先設定(※Phase 1 では設定の読み込みのみ。インデクサーへの反映は別Issue)
languages = ["markdown", "typescript", "python"]
[search]
# デフォルトの検索結果件数(CLI引数が明示指定された場合はCLI引数を優先)
default_limit = 20
# デフォルトのスニペット行数
snippet_lines = 2
snippet_chars = 120
[embedding]
# チーム統一のEmbeddingプロバイダー
provider = "ollama"
model = "nomic-embed-text"
endpoint = "http://localhost:11434"
[rerank]
provider = "ollama"
model = "bge-reranker-v2-m3"
CLI連携
# 現在の有効設定を表示(TOML形式、秘匿値はマスク表示)
commandindex config show
# 読み込まれた設定ファイルのパスを優先順位順に表示(存在するもののみ)
# 旧 .commandindex/config.toml が存在する場合は [deprecated] 注記付きで表示
commandindex config path
注: --format オプション(json/human)は Phase 1 ではスコープ外。TOML形式のみサポート。
CLI引数と設定ファイルの優先関係
CLI引数(明示指定時) > 環境変数 > config.local.toml > commandindex.toml > 旧config.toml(deprecated) > デフォルト値
- CLI引数が明示的に指定された場合はCLI引数を優先
- CLI引数が未指定(デフォルト値)の場合は設定ファイルの値を使用
- 対象:
--limit, --snippet-lines, --snippet-chars 等の検索関連引数
- 実装方針: clap の
default_value_t を使わず Option<usize> にし、None の場合に config → ハードコードデフォルトの順でフォールバック
設定ファイルの検出方法
--path 引数を持つコマンド(index, update, embed, clean): --path で指定されたディレクトリをベースパスとして使用
--path 引数を持たないコマンド(search, config): カレントディレクトリをベースパスとして使用
commandindex.toml は {base_path}/commandindex.toml から読み込み
.commandindex/config.local.toml は {base_path}/.commandindex/config.local.toml から読み込み
既存設定ファイルからの移行
- 既存の
.commandindex/config.toml は deprecated fallback として読み込みを維持
.commandindex/config.toml が存在する場合は 警告メッセージを stderr に出力(deprecated fallback を実際に使用した場合のみ1回)
- 警告出力条件:
- 旧設定のみ存在: 読み込んで警告「commandindex.toml への移行を推奨」
- 新旧両方存在: 新設定を優先し、旧設定は無視。警告「旧設定は無視されています」
- 優先順位:
commandindex.toml > .commandindex/config.toml(旧ファイルは最低優先)
clean.rs のハードコード参照を更新:
.commandindex/ 配下の保持対象: config.local.toml, config.toml(旧)
- ルートの
commandindex.toml は .commandindex/ 外なので clean の対象外
- これは breaking change ではない: 旧ファイルは引き続き読み込まれるため既存ユーザーの動作は維持される
実装方針
-
config モジュール新規作成(src/config/mod.rs)
- 全設定セクション(index, search, embedding, rerank)を統合管理する
AppConfig 構造体を定義
- マージ用の中間構造体(全フィールド
Option<T>)で設定ソースを読み込み、フィールドレベルマージを実施
- 専用エラー型
ConfigError enum を定義
EmbeddingConfig, RerankConfig は現在のモジュール(embedding/rerank)に型定義を残し、AppConfig から参照する設計(循環依存を回避)
- 設定ファイル名を定数化:
TEAM_CONFIG_FILE, LOCAL_CONFIG_FILE, LEGACY_CONFIG_FILE
- config を唯一の設定読込入口にする原則を適用
-
既存 embedding::Config の移行
embedding::Config および embedding::EmbeddingConfig の設定読み込みロジックを config モジュールに移行
embedding::Config は削除し、全呼び出し箇所を config::AppConfig に更新
- 対象箇所:
cli/search.rs(4箇所)、cli/embed.rs(1箇所)、cli/index.rs(1箇所)
clean.rs の config.toml ハードコード参照も更新(LOCAL_CONFIG_FILE, LEGACY_CONFIG_FILE を保持対象に)
-
Serialize 対応と config show 用 view model
EmbeddingConfig, RerankConfig に Serialize derive を追加
config show 用のマスク済み表示構造体(view model)を別途用意
- 秘匿値(api_key 等)はマスク表示(
***)を保証
-
toml crate でパース(既にCargo.tomlに toml = "0.8" 依存済み)
-
CLIサブコマンド追加
config show / config path サブコマンドを src/cli/config.rs に実装
- Commands enum にネストした ConfigCommands を追加
config show は秘匿値を必ずマスク表示
config path は旧設定ファイルがあれば [deprecated] 注記付きで表示
-
CLIデフォルト値の変更
--limit, --snippet-lines, --snippet-chars を Option<usize> に変更
- 未指定時は config → ハードコードデフォルトの順でフォールバック
-
Config::load() の呼び出し最適化
- search.rs 内で最大4回呼ばれる現状を改善
- AppConfig::load() の結果を1回だけ生成し、各関数に引数として渡す設計にリファクタリング
-
エラー型の整理
- 新
config::ConfigError enum を作成
- 既存
EmbeddingError::ConfigError(String) は config::ConfigError からの From 変換で生成
-
deprecated 警告の統一
- 警告メッセージは stderr に出力
- deprecated fallback を実際に使用した場合のみ1回出力
- 新旧両方存在して旧設定が無視される場合も別メッセージで通知
-
テストの更新
tests/e2e_embedding.rs と tests/e2e_semantic_hybrid.rs の .commandindex/config.toml 参照を新パスに更新
tests/cli_args.rs に config show / config path のテストを追加
- 設定ファイル名を定数化してDRYに(テストヘルパーでも定数を使用)
- E2Eテスト3系統: commandindex.toml のみ、config.local.toml 上書き、legacy config.toml fallback
- CLI引数優先順位テスト: 「未指定時はハードコード既定値」「設定あり時は設定値」「CLI明示時はCLI優先」
- clean --keep-embeddings の回帰テスト
- 各コマンドのベースパス別設定検出テスト
受け入れ基準
依存 Issue
概要
チームで共有可能な設定ファイル
commandindex.tomlをリポジトリルートに配置し、インデックス設定やEmbeddingプロバイダー設定をチーム全体で統一できるようにする。背景・動機
現在の設定は
.commandindex/内に閉じており、.gitignoreで除外されるためチーム共有ができない。チームで同じ設定(除外パターン、Embeddingモデル、検索デフォルト等)を使いたい場合に、各メンバーが個別に設定する必要がある。提案する解決策
設定ファイルの優先順位
マージ仕様
マージ例:
環境変数オーバーライド
Phase 1 では以下の環境変数のみサポート(既存互換):
COMMANDINDEX_OPENAI_API_KEY: OpenAI APIキーの上書き将来的に
COMMANDINDEX_EMBEDDING_PROVIDER,COMMANDINDEX_EMBEDDING_MODEL等の網羅的な環境変数対応は別Issueで対応予定。設定ファイルフォーマット
CLI連携
注:
--formatオプション(json/human)は Phase 1 ではスコープ外。TOML形式のみサポート。CLI引数と設定ファイルの優先関係
--limit,--snippet-lines,--snippet-chars等の検索関連引数default_value_tを使わずOption<usize>にし、None の場合に config → ハードコードデフォルトの順でフォールバック設定ファイルの検出方法
--path引数を持つコマンド(index, update, embed, clean):--pathで指定されたディレクトリをベースパスとして使用--path引数を持たないコマンド(search, config): カレントディレクトリをベースパスとして使用commandindex.tomlは{base_path}/commandindex.tomlから読み込み.commandindex/config.local.tomlは{base_path}/.commandindex/config.local.tomlから読み込み既存設定ファイルからの移行
.commandindex/config.tomlは deprecated fallback として読み込みを維持.commandindex/config.tomlが存在する場合は 警告メッセージを stderr に出力(deprecated fallback を実際に使用した場合のみ1回)commandindex.toml>.commandindex/config.toml(旧ファイルは最低優先)clean.rsのハードコード参照を更新:.commandindex/配下の保持対象:config.local.toml,config.toml(旧)commandindex.tomlは.commandindex/外なので clean の対象外実装方針
config モジュール新規作成(
src/config/mod.rs)AppConfig構造体を定義Option<T>)で設定ソースを読み込み、フィールドレベルマージを実施ConfigErrorenum を定義EmbeddingConfig,RerankConfigは現在のモジュール(embedding/rerank)に型定義を残し、AppConfigから参照する設計(循環依存を回避)TEAM_CONFIG_FILE,LOCAL_CONFIG_FILE,LEGACY_CONFIG_FILE既存 embedding::Config の移行
embedding::Configおよびembedding::EmbeddingConfigの設定読み込みロジックをconfigモジュールに移行embedding::Configは削除し、全呼び出し箇所をconfig::AppConfigに更新cli/search.rs(4箇所)、cli/embed.rs(1箇所)、cli/index.rs(1箇所)clean.rsの config.toml ハードコード参照も更新(LOCAL_CONFIG_FILE, LEGACY_CONFIG_FILE を保持対象に)Serialize 対応と config show 用 view model
EmbeddingConfig,RerankConfigにSerializederive を追加config show用のマスク済み表示構造体(view model)を別途用意***)を保証toml crate でパース(既にCargo.tomlに
toml = "0.8"依存済み)CLIサブコマンド追加
config show/config pathサブコマンドをsrc/cli/config.rsに実装config showは秘匿値を必ずマスク表示config pathは旧設定ファイルがあれば [deprecated] 注記付きで表示CLIデフォルト値の変更
--limit,--snippet-lines,--snippet-charsをOption<usize>に変更Config::load() の呼び出し最適化
エラー型の整理
config::ConfigErrorenum を作成EmbeddingError::ConfigError(String)はconfig::ConfigErrorからのFrom変換で生成deprecated 警告の統一
テストの更新
tests/e2e_embedding.rsとtests/e2e_semantic_hybrid.rsの.commandindex/config.toml参照を新パスに更新tests/cli_args.rsにconfig show/config pathのテストを追加受け入れ基準
commandindex.tomlをリポジトリルートに配置してチーム共有設定ができる.commandindex/config.local.tomlで個人オーバーライドができるCOMMANDINDEX_OPENAI_API_KEYで最優先オーバーライドができるcommandindex config showで有効設定をTOML形式で表示できる(秘匿値はマスク、view model 経由)commandindex config pathで読み込まれた設定ファイルのパスを表示できる(旧ファイルは[deprecated]注記付き).commandindex/config.tomlが存在する場合は deprecated fallback として読み込み、警告メッセージを stderr に出力clean.rsの保持対象が LOCAL_CONFIG_FILE, LEGACY_CONFIG_FILE に更新されている(ルートの commandindex.toml は対象外)ConfigErrorが定義されている.commandindex/config.local.tomlが.gitignoreで除外されていること(.commandindex/が既に除外済みなら確認のみ)依存 Issue