カスタムプロバイダー
ダッシュボードの Providers タブは、ADHDev があるマシンで何を検出・制御できるかを 示す場所であり、新しいプロバイダーをゼロから作る場所ではありません。ADHDev が まだ知らない CLI・IDE・エージェントに対応させるには、小さな JSON ファイル (「プロバイダーマニフェスト」)を書いて、デーモンがすでに監視しているフォルダに 置くだけです。このページではその流れを最初から最後まで説明します。
プロバイダーとは何か
ADHDev には 3 つのプロバイダーカテゴリがあります:
cli— Claude Code や Codex CLI のように、PTY(疑似端末)経由で操作 される端末エージェント。デーモンが端末に入力し、画面を読み取ります。ide— Chrome DevTools Protocol 経由で検査・制御される CDP 駆動の コードエディタ(Cursor、VS Code 派生版など)。extension— CDP 駆動の IDE 拡張の webview(Cline、Roo Code など)。
現実的に自分で書く価値があるのは cli カテゴリです。 CLI プロバイダーは JSON マニフェストと、画面上で「生成中」「アイドル」「承認待ち」をどう見分けるかを 記述する JSON ステートマシンのスペックだけで構成され、コードは不要です。
ide と extension プロバイダーは事情が異なります。パネルを開く、チャットを 読む、メッセージを送るといった処理を行う実際の CDP 自動化スクリプト (JavaScript)が必要です。端末の画面状態を記述するよりもはるかに大きな作業に なるため、このページの対象外です。それでも挑戦したい場合は、下記の プロバイダー SDK ガイド の 参考資料を参照してください。
このページの残りは CLI プロバイダーについてです。
ファイルの置き場所
デーモンは次の優先順位でいくつかのディレクトリからプロバイダーを読み込みます (同じプロバイダータイプについては、後にあるものが前のものを上書きします):
- アップストリーム —
<configDir>/providers/.upstream/— 公式に 自動同期されるバンドル。手動で編集しないでください。上書きされます。 - 外部ソース —
<configDir>/external/<source-name>/— ダッシュボードの Sources パネルから登録するサードパーティの git ソース。 - ユーザーオーバーライド —
<configDir>/providers/(.upstream/を 除く すべて)— 自分で作成・上書きするマニフェスト。常にこれが 優先されます。 通常のインストールでは<configDir>は~/.adhdevな ので、ここは~/.adhdev/providers/です。
各プロバイダーは次の場所にあります:
<root>/<category>/<type>/
provider.v1.json ← マニフェスト(必須)
specs/
<version>.json ← FSM ステートマシンスペック(cli では必須)cli/<type>/provider.v1.json を ~/.adhdev/providers/ に置くだけで十分 です — 他のどこにも登録する必要はありません。
何も表示されない場合は、すでに providerDir が設定されていないか確認して ください。 明示的な providerDir(Sources パネルまたは設定で設定 — 下記の「デーモンに別のフォルダを見させる」参照)は、デフォルトの ~/.adhdev/providers/ に追加するのではなく、ユーザーオーバーライド フォルダを置き換えます。デーモン自身のログにはこれが userDirSource: "explicit" として記録されます。マシンにすでにそれが 設定されている場合、新しいマニフェストは ~/.adhdev/providers/ ではなく そのフォルダに置く必要があり、ホットリロードもその 1 つのアクティブな フォルダしか監視しません(下記の「どのフォルダがアクティブか確認する」 参照)。
「アップストリームを上書きする」の正確な意味
デーモンがすでに提供しているものと同じ type を持つプロバイダーを作成すると (たとえば手を加えた claude-cli)、~/.adhdev/providers/cli/claude-cli/ にあるあなたのコピーがアップストリーム版の 代わりに 読み込まれます。デーモンは これを明示的にログに記録する(⚠ OVERRIDES upstream)ので、これが起きたことが 見えるようになっています。これは、アップストリームの修正を待たずに内蔵 プロバイダーの 1 フィールドだけをパッチする方法でもあります — プロバイダー ディレクトリ全体をユーザーフォルダにコピーして、そこで編集してください。
デーモンに別のフォルダを見させる
デフォルトでは、デーモンはユーザーオーバーライド用に ~/.adhdev/providers/ だけを監視します。カスタムプロバイダーを別の場所(たとえば作業中の git チェックアウト)に置いておきたい場合は、明示的なプロバイダーディレクトリを 設定してください:
- ダッシュボード: Machine ページ → Providers タブ → Advanced → Provider source mode(
normalまたはno-upstream)と Provider directory を設定し、Apply & reload。no-upstreamは自動同期される アップストリームバンドルを完全に無効化し、自分のディレクトリとexternal/の内容だけを提供します。 - 設定ファイル: デーモンの設定で
providerDir(と、必要に応じてproviderSourceMode)を設定します。
いずれの方法でも、変更を適用するとデーモンの set_provider_source_config コマンドが呼ばれ、プロバイダーマップが即座に再読み込みされます — デーモンの再起動は不要です。
どのフォルダがアクティブか確認する
明示的な providerDir はデフォルトに追加されるのではなく置き換えるため、 マニフェストが読み込まれない理由を探す前に、デーモンが実際にどのフォルダを 監視しているかを確認しておく価値があります:
- ダッシュボード: Machine ページ → Providers タブ → Advanced で、 現在の Provider directory の値が表示されます(空欄はデフォルトの
~/.adhdev/providers/を意味します)。 - デーモンのログ:
Hot-reload watcher active: <dir>という行を 探してください —<dir>が実際に監視されているフォルダです。デーモンの ログは、インストール形態(クラウドデーモン、standalone、プレビュー インスタンス)に関係なく~/.adhdev/logs/daemon-YYYY-MM-DD.logに あります。
ユーザーオーバーライドフォルダのホットリロード
デーモンが実行されている間、ユーザーオーバーライドディレクトリ (~/.adhdev/providers/、または providerDir に設定した場所)ただ 1 つの .js と .json ファイルの変更を監視します — アクティブなユーザー オーバーライドディレクトリは常に 1 つだけで、両方が同時に監視される ことはありません。そこでマニフェストを編集すると、約 300ms 以内に 反映されます — 再起動も手動リロードも不要です。この監視は .upstream/ や external/ のソースツリーは対象外です — そちらの変更は adhdev provider reload(またはダッシュボードの再読み込み)で反映する 必要があります。
クイックスタート: adhdev provider init
下記の 2 つのファイルを最速でディスク上に用意する方法は、CLI に 生成させることです:
adhdev provider init my-cli --dir ./my-cliこれは現在の v1 形式で provider.v1.json と specs/1.0.json を スキャフォールディングします — このページがこの次に手作業でたどる のと同じ形です。バイナリ名は <type> から導出され(末尾の -cli を除去するか、--binary で明示的に指定)、スペック内の プレースホルダー正規表現は、対象コマンドの実際の画面出力に本当に マッチするパターンに自分で置き換える必要があります。 init は --category ide と --category extension を拒否します — これらは特定の IDE・webview 専用の手書き CDP 自動化スクリプトが 必要で、実際に動くものを生成できる汎用テンプレートが存在しないためです。
その直後に adhdev provider validate ./my-cli を実行してみてください — プレースホルダーの正規表現で失敗するはずです(絶対にマッチしない ため)が、それが狙いです。まだスタブの部分と、スキーマがすでに 受け入れる部分を正確に教えてくれます。
最小限の動作する CLI プロバイダー
CLI プロバイダーは宣言的な有限状態マシンエンジン(「スペック」)を通じて ルーティングされます。スペックは必須です — 以前のスクリプトベースの CLI エンジンは削除されており、スペックが解決できない CLI プロバイダーは、より 弱いエンジンにフォールバックする代わりに、明示的なエラーで起動に失敗する ようになりました。したがって最小限のプロバイダーは 2 つのファイルで 構成されます: マニフェストと、有効な最小限のスペックです。(これは 上記で adhdev provider init がスキャフォールディングするのと同じ 形です — 生成されたファイルを編集する場合も、手で書く場合も、各部分が どう動くかは以下で説明します。)
対象コマンドを選ぶ
実際にライブでテストできるマニフェストにするには、実在し、無害で、すでに インストールされているインタラクティブなコマンドを選んでください。 python3 -q は良い選択です。事実上あらゆる macOS・Linux マシンに搭載されて おり、「quiet」モードで起動する(バージョンバナーをスキップするので照合 対象が減る)うえ、その >>> プロンプトは生の bash プロンプト(PS1)が シェル設定に依存するのとは違い、「アイドル」を示すシンプルで安定したマーカー です。
provider.v1.json
{
"$schema": "https://registry.adhf.dev/schemas/v1/cli/provider.schema.json",
"type": "python-repl",
"name": "Python REPL",
"category": "cli",
"binary": "python3",
"spawn": {
"command": "python3",
"args": ["-q"],
"shell": false
},
"compatibility": [
{ "ideVersion": ">=0.0.0", "spec": "specs/1.0.json" }
]
}スキーマが実際に要求するフィールド(type、name、category、binary、 spawn)のみに加えて、compatibility があります — これはローダーが下記の スペックファイルを見つける方法です。
specs/1.0.json
{
"$schema": "adhdev:cli/spec@4",
"id": "python-repl",
"name": "Python REPL",
"binary": "python3",
"send_message": {
"submit_key": "\r"
},
"states": [
{ "id": "starting", "label": "Starting", "initial": true, "status": "idle" },
{ "id": "idle", "label": "Ready", "status": "idle" },
{ "id": "busy", "label": "Evaluating", "status": "generating" }
],
"transitions": [
{
"label": "startup → idle",
"from": "starting",
"to": "idle",
"when": { "matches": ">>>\\s*(?=\\n|$)" }
},
{
"label": "idle → busy",
"from": "idle",
"to": "busy",
"min_hold_ms": 200,
"when": { "not": { "matches": ">>>\\s*(?=\\n|$)" } }
},
{
"label": "busy → idle",
"from": "busy",
"to": "idle",
"min_hold_ms": 300,
"when": {
"all": [
{ "matches": ">>>\\s*(?=\\n|$)" },
{ "stable_ms": 500 }
]
}
}
]
}これが FSM バリデータが要求する実際の最小限です: id、binary、 send_message.submit_key、ちょうど 1 つの initial: true 状態を持つ空で ない states[]、そして transitions[] 配列。実際のプロバイダースペックに ある他のすべて(承認モーダルの検出、セクションウィンドウ、ネイティブな チャット履歴、自動承認モードなど)は、この形の上に追加されるものです — これが動くようになったら、より完全な例として adhdev-providers/cli/*/specs/ 配下の内蔵スペックを参照してください。
なぜ
$ではなく(?=\n|$)なのか?matchesパターンは画面全体の バッファに対して実行され、行単位ではありません。エンジンはデフォルトでmフラグなしでパターンをコンパイルするため、エスケープされていない$はプロンプト行の末尾ではなく画面全体の末尾にアンカーされ、プロンプト の下に何かある限り静かに一切マッチしなくなります。スペックのリンターは まさにこの理由で、mなしでも機能するいくつかの行境界イディオムを ホワイトリストに入れています(行末は(?=\n|$)、行頭は(?:^|\n))。 素のアンカーの代わりにこれらを使うことが、このパターンがプロンプト行に 実際に確実にマッチする理由です。
両方のファイルを ~/.adhdev/providers/cli/python-repl/provider.v1.json と ~/.adhdev/providers/cli/python-repl/specs/1.0.json に置いたら、先に プロバイダーを有効化してから(adhdev provider enable python-repl または ダッシュボードの Machine Providers トグル — ダッシュボード自体の検出 チェックは無効なプロバイダーを拒否します。下記参照)、それに対して セッションを起動してみてください。python3 はすでにインストールされて いるので、試す前に他に用意するものはありません。
プロバイダーを検証する
adhdev provider validate <path>はprovider.v1.json(またはレガシーのprovider.json)を、デーモンがロード時に使うのと同じ v1 JSON スキーマで 検証し、どのティアに該当するかを報告します。cliマニフェストについては、 デーモンが起動時に行うのと同じ方法でスペックを解決し (compatibility[].spec→specs/default.json→spec.json)、 デーモンと同じ FSM バリデータにかけます — スキーマは通るがスペックが 解決できないマニフェストや、ステートマシンの形が不正なスペックは、 後で起動時に失敗する(formatNoResolvableSpecError)代わりに、 ここで無効として報告されます。上記の例ではtier: extended-legacyとpython-repl@unversionedが表示されますが、どちらも想定どおりで問題 ありません:extended-legacyは単に「他の 2 つのティアのどちらでもない」と いう意味です。extendedはマニフェストがoverridesブロック (カスタム JS フック)を宣言していることを意味し、declarative-onlyはtuiブロックを宣言していることを意味します。 この例のようにoverridesもtuiもない、素のスペックルーティング マニフェストは、消去法でextended-legacyになります。何かが不足 しているという意味ではありません。unversionedは単に、マニフェストにproviderVersionフィールドが ないことを意味します。スキーマはこれを必須にしておらず、ローダーも CLI プロバイダーのロードや実行にこのフィールドを必要としません —provider list/validateが何かを表示できるようにするためだけに 存在します。実際の値を表示したい場合は"providerVersion": "1.0.0"フィールドを追加できますが、このような マニフェストでは見た目だけの問題です。
adhdev provider list(機械可読な出力には--jsonを追加)は、デーモンが 現在ロードしているすべてのプロバイダーを、すべてのソースディレクトリに わたってスペックのバージョンピンとともに表示します。adhdev provider detect [type]は、実際にそのバイナリがインストール されPATH上にあるかを確認します。CLI から実行した場合は意図的に 有効化ゲートをバイパスするため、プロバイダーを有効化する前でも動作 します。ダッシュボード/デーモン側の同等機能(detect_provider)は より厳格で、プロバイダーがまだ有効化されていない場合はProvider is disabled on this machineで拒否します。そのため、CLI ではなくダッシュボードから検出を確認する場合は、先にプロバイダーを 有効化してください。- デーモンの実行中にユーザーオーバーライドフォルダのマニフェストを編集 すると、上記のホットリロードウォッチャーが発動します — デーモンのログで
File changed: provider.v1.json, reloading...と、⚠の検証警告が ないか確認してください。
このような手書きの、ツリー外(out-of-tree)のプロバイダー向けの ダッシュボードの「fix」や自動修復フローはありません — そのツールは、 あなたが自分で保守するカスタムマニフェストではなく、内蔵プロバイダー バンドル自体のスクリプトレイアウトを対象としています。
共有する
作成したプロバイダーを誰もが自動的に受け取る内蔵セットの一部にしたい場合は、 デーモンの .upstream/ バンドルがビルドされる、まさにそのリポジトリである github.com/vilmire/adhdev-providersに アップストリームとして貢献してください。 リポジトリ自体のコントリビューションガイドに 従って、cli/<type>/ ディレクトリを追加するプルリクエストを開いてください。 そこに取り込まれることで、プロバイダーは内蔵インベントリの一部にはなり ますが、自動的に検証済みプロバイダーになるわけではないことに注意して ください — その違いについては プロバイダーの問題 を 参照してください。
それまでの間(あるいはその代わりに)、プロバイダーディレクトリはただの フォルダです — バージョン管理下に置いたり、zip として共有したり、チーム メンバーの providerDir を同じ git チェックアウトに向けさせたりできます。
関連ドキュメント
- プロバイダーの問題 — 内蔵プロバイダーが 誤動作したときにすべきこと。
- CLI エージェント — ADHDev がすでにサポートしている CLI エージェントの使い方。
- 互換性と注意事項
