커스텀 프로바이더
대시보드의 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 확장 웹뷰(Cline, Roo Code 등).
현실적으로 직접 작성해볼 만한 것은 cli 카테고리입니다. CLI 프로바이더는 JSON 매니페스트와, 화면에서 "생성 중" / "유휴" / "승인 대기"를 어떻게 구분하는지 설명하는 JSON 상태 머신 스펙만으로 구성됩니다 — 코드가 필요하지 않습니다.
ide와 extension 프로바이더는 이야기가 다릅니다: 패널을 열고, 채팅을 읽고, 메시지를 보내는 등의 작업을 하는 실제 CDP 자동화 스크립트(JavaScript)가 필요합니다. 이는 터미널의 화면 상태를 설명하는 것보다 훨씬 큰 작업이며, 이 페이지의 범위를 벗어납니다 — 그래도 시도해보고 싶다면 아래의 프로바이더 SDK 가이드 참고 자료를 확인하세요. acp 프로바이더도 직접 만들 수 있지만(PTY 화면 스크래핑이 필요 없음) CLI 프로바이더보다는 추가하는 경우가 드뭅니다.
이 페이지의 나머지 부분은 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/가 아니라 그 폴더에 넣어야 하며, 핫 리로드도 그 활성 폴더 하나만 감시합니다(아래 "어느 폴더가 활성 상태인지 확인하기" 참고).
"업스트림을 오버라이드한다"의 정확한 의미
데몬이 이미 제공하는 것과 같은 type을 가진 프로바이더를 만들면(예: 수정한 claude-cli), ~/.adhdev/providers/cli/claude-cli/에 있는 여러분의 사본이 업스트림 것 대신 로드됩니다. 데몬은 이를 명시적으로 로그에 남기므로 (⚠ OVERRIDES upstream) 이런 일이 벌어질 때 눈에 보입니다. 업스트림 수정을 기다리지 않고 내장 프로바이더의 필드 하나를 패치하는 방법이기도 합니다 — 프로바이더 디렉터리 전체를 사용자 폴더로 복사해서 그곳에서 편집하면 됩니다.
데몬이 다른 폴더를 보게 하기
기본적으로 데몬은 사용자 오버라이드를 위해 ~/.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로 설정한 곳) 단 하나만의 .js와 .json 파일 변경을 감시합니다 — 활성 사용자 오버라이드 디렉터리는 항상 하나뿐이며 둘 다 동시에 감시되는 일은 없습니다. 그곳의 매니페스트를 편집하면 약 300ms 내에 반영됩니다 — 재시작도 수동 리로드도 필요 없습니다. 이 감시는 .upstream/이나 external/ 소스 트리는 대상이 아닙니다 — 그곳의 변경사항은 adhdev provider reload(또는 대시보드 새로고침)로 반영해야 합니다.
빠른 시작: adhdev provider init
아래 두 파일을 디스크에 가장 빨리 준비하는 방법은 CLI가 생성하게 하는 것입니다:
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/웹뷰 전용의 손으로 작성한 CDP 자동화 스크립트가 필요하므로, 실제로 동작하는 결과물을 만들어낼 범용 템플릿이 없기 때문입니다.
바로 이어서 adhdev provider validate ./my-cli를 실행해보세요 — 자리 표시자 정규식에서 실패할 텐데(절대 매칭되지 않으므로), 이것이 의도된 동작입니다: 아직 스텁인 부분과 스키마가 이미 받아들이는 부분을 정확히 알려줍니다.
최소 동작 CLI 프로바이더
CLI 프로바이더는 선언적 유한 상태 머신 엔진("스펙")을 통해 라우팅됩니다. 스펙은 필수입니다 — 예전의 스크립트 기반 CLI 엔진은 제거되었고, 스펙을 찾을 수 없는 CLI 프로바이더는 이제 더 약한 엔진으로 폴백하는 대신 명시적인 오류와 함께 실행에 실패합니다. 따라서 최소 프로바이더는 두 파일로 구성됩니다: 매니페스트와, 유효한 최소 스펙입니다.(이는 위에서 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, 정확히 하나의 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**는 그냥 "나머지 두 티어 어디에도 속하지 않는다"는 뜻입니다: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 에이전트 사용하기.
- 호환성 및 주의사항
