Skip to content

カスタムプロバイダー ​

ダッシュボードの Providers タブは、ADHDev があるマシンで何を検出・制御できるかを 示す場所であり、新しいプロバイダーをゼロから作る場所ではありません。ADHDev が まだ知らない CLI・IDE・エージェントに対応させるには、小さな JSON ファイル (「プロバイダーマニフェスト」)を書いて、デーモンがすでに監視しているフォルダに 置くだけです。このページではその流れを最初から最後まで説明します。

プロバイダーとは何か ​

ADHDev には 4 つのプロバイダーカテゴリがあります:

  • cli — Claude Code や Codex CLI のように、PTY(疑似端末)経由で操作 される端末エージェント。デーモンが端末に入力し、画面を読み取ります。
  • acp — Agent Client Protocol を stdio 上で話すエージェント(画面スクレイピングではなく構造化メッセージ)。
  • ide — Chrome DevTools Protocol 経由で検査・制御される CDP 駆動の コードエディタ(Cursor、VS Code 派生版など)。
  • extension — CDP 駆動の IDE 拡張の webview(Cline、Roo Code など)。

現実的に自分で書く価値があるのは cli カテゴリです。 CLI プロバイダーは JSON マニフェストと、画面上で「生成中」「アイドル」「承認待ち」をどう見分けるかを 記述する JSON ステートマシンのスペックだけで構成され、コードは不要です。

ide と extension プロバイダーは事情が異なります。パネルを開く、チャットを 読む、メッセージを送るといった処理を行う実際の CDP 自動化スクリプト (JavaScript)が必要です。端末の画面状態を記述するよりもはるかに大きな作業に なるため、このページの対象外です。それでも挑戦したい場合は、下記の プロバイダー SDK ガイド の 参考資料を参照してください。acp プロバイダーも手作業で作成できますが (PTY の画面スクレイピングは不要)、CLI プロバイダーほど頻繁には追加されません。

このページの残りは CLI プロバイダーについてです。

ファイルの置き場所 ​

デーモンは次の優先順位でいくつかのディレクトリからプロバイダーを読み込みます (同じプロバイダータイプについては、後にあるものが前のものを上書きします):

  1. アップストリーム — <configDir>/providers/.upstream/ — 公式に 自動同期されるバンドル。手動で編集しないでください。上書きされます。
  2. 外部ソース — <configDir>/external/<source-name>/ — ダッシュボードの Sources パネルから登録するサードパーティの git ソース。
  3. ユーザーオーバーライド — <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 に 生成させることです:

bash
adhdev provider init my-cli --dir ./my-cli

これは現在の v1 形式で provider.v1.json と specs/1.0.json を スキャフォールディングします — このページがこの次に手作業でたどる のと同じ形です。バイナリ名は <type> から導出され(末尾の -cli/-acp を除去するか、--binary で明示的に指定)、スペック内の プレースホルダー正規表現は、対象コマンドの実際の画面出力に本当に マッチするパターンに自分で置き換える必要があります。 adhdev provider init my-acp --category acp --dir ./my-acp は宣言的な ACP プロバイダーに対して同じことを行います(スペックファイルなしで provider.v1.json 一つだけ — 上記の「プロバイダーとは何か」を参照)。 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 ​

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 ​

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 はすでにインストールされて いるので、試す前に他に用意するものはありません。

上記の例のファイルは、そのままコピーして使えるように、このガイドのソースの 隣にある custom-provider-example/ にもまとめて保存されています。

プロバイダーを検証する ​

  • adhdev provider validate <path> は provider.v1.json(またはレガシーの provider.json)を、デーモンがロード時に使うのと同じ v1 JSON スキーマで 検証し、どのティアに該当するかを報告します。cli マニフェストについては、 デーモンが起動時に行うのと同じ方法でスペックを解決し (compatibility[].spec → specs/default.json → spec.json)、 デーモンと同じ FSM バリデータにかけます — スキーマは通るがスペックが 解決できないマニフェストや、ステートマシンの形が不正なスペックは、 後で起動時に失敗する(formatNoResolvableSpecError)代わりに、 ここで無効として報告されます。acp マニフェストにはスペックという 概念自体がなく、この手順はスキップされます。上記の例では 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 チェックアウトに向けさせたりできます。

関連ドキュメント ​

ホスティングされたクラウドのドキュメントはこちらです。オープンソースおよびセルフホストのドキュメントは OSS リポジトリにあります。