adde-acp 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.ko.md +88 -0
- package/README.md +88 -0
- package/dist/backend/acp/client.d.ts +149 -0
- package/dist/backend/acp/client.js +538 -0
- package/dist/backend/acp/client.js.map +1 -0
- package/dist/backend/acp/index.d.ts +8 -0
- package/dist/backend/acp/index.js +7 -0
- package/dist/backend/acp/index.js.map +1 -0
- package/dist/backend/acp/lifecycle.d.ts +15 -0
- package/dist/backend/acp/lifecycle.js +56 -0
- package/dist/backend/acp/lifecycle.js.map +1 -0
- package/dist/backend/acp/perm-diff.d.ts +37 -0
- package/dist/backend/acp/perm-diff.js +58 -0
- package/dist/backend/acp/perm-diff.js.map +1 -0
- package/dist/backend/acp/spawn.d.ts +20 -0
- package/dist/backend/acp/spawn.js +70 -0
- package/dist/backend/acp/spawn.js.map +1 -0
- package/dist/cli/adde.d.ts +2 -0
- package/dist/cli/adde.js +11 -0
- package/dist/cli/adde.js.map +1 -0
- package/dist/cli/alias.d.ts +45 -0
- package/dist/cli/alias.js +94 -0
- package/dist/cli/alias.js.map +1 -0
- package/dist/cli/completion.d.ts +4 -0
- package/dist/cli/completion.js +209 -0
- package/dist/cli/completion.js.map +1 -0
- package/dist/cli/init.d.ts +3 -0
- package/dist/cli/init.js +114 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/lane.d.ts +20 -0
- package/dist/cli/lane.js +350 -0
- package/dist/cli/lane.js.map +1 -0
- package/dist/cli/ops.d.ts +5 -0
- package/dist/cli/ops.js +230 -0
- package/dist/cli/ops.js.map +1 -0
- package/dist/cli/prompt.d.ts +15 -0
- package/dist/cli/prompt.js +41 -0
- package/dist/cli/prompt.js.map +1 -0
- package/dist/cli/run.d.ts +5 -0
- package/dist/cli/run.js +216 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/spec.d.ts +48 -0
- package/dist/cli/spec.js +98 -0
- package/dist/cli/spec.js.map +1 -0
- package/dist/core/diagnostics.d.ts +73 -0
- package/dist/core/diagnostics.js +333 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/index.d.ts +11 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/injector.d.ts +27 -0
- package/dist/core/injector.js +297 -0
- package/dist/core/injector.js.map +1 -0
- package/dist/core/lane-config.d.ts +80 -0
- package/dist/core/lane-config.js +303 -0
- package/dist/core/lane-config.js.map +1 -0
- package/dist/core/launchd.d.ts +81 -0
- package/dist/core/launchd.js +216 -0
- package/dist/core/launchd.js.map +1 -0
- package/dist/core/messages.d.ts +31 -0
- package/dist/core/messages.js +71 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/queue.d.ts +74 -0
- package/dist/core/queue.js +227 -0
- package/dist/core/queue.js.map +1 -0
- package/dist/core/runtime-state.d.ts +52 -0
- package/dist/core/runtime-state.js +90 -0
- package/dist/core/runtime-state.js.map +1 -0
- package/dist/core/session-ledger.d.ts +25 -0
- package/dist/core/session-ledger.js +89 -0
- package/dist/core/session-ledger.js.map +1 -0
- package/dist/core/supervisor.d.ts +41 -0
- package/dist/core/supervisor.js +315 -0
- package/dist/core/supervisor.js.map +1 -0
- package/dist/core/transcript.d.ts +22 -0
- package/dist/core/transcript.js +93 -0
- package/dist/core/transcript.js.map +1 -0
- package/dist/core/update-check.d.ts +25 -0
- package/dist/core/update-check.js +142 -0
- package/dist/core/update-check.js.map +1 -0
- package/dist/core/version.d.ts +7 -0
- package/dist/core/version.js +32 -0
- package/dist/core/version.js.map +1 -0
- package/dist/gate/gate.d.ts +41 -0
- package/dist/gate/gate.js +28 -0
- package/dist/gate/gate.js.map +1 -0
- package/dist/gate/index.d.ts +6 -0
- package/dist/gate/index.js +6 -0
- package/dist/gate/index.js.map +1 -0
- package/dist/shared/conf.d.ts +54 -0
- package/dist/shared/conf.js +85 -0
- package/dist/shared/conf.js.map +1 -0
- package/dist/shared/deny-match.d.ts +19 -0
- package/dist/shared/deny-match.js +122 -0
- package/dist/shared/deny-match.js.map +1 -0
- package/dist/shared/envelope.d.ts +37 -0
- package/dist/shared/envelope.js +91 -0
- package/dist/shared/envelope.js.map +1 -0
- package/dist/shared/errors.d.ts +8 -0
- package/dist/shared/errors.js +23 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/fs-atomic.d.ts +17 -0
- package/dist/shared/fs-atomic.js +31 -0
- package/dist/shared/fs-atomic.js.map +1 -0
- package/dist/shared/i18n.d.ts +23 -0
- package/dist/shared/i18n.js +53 -0
- package/dist/shared/i18n.js.map +1 -0
- package/dist/shared/locales/en.d.ts +393 -0
- package/dist/shared/locales/en.js +447 -0
- package/dist/shared/locales/en.js.map +1 -0
- package/dist/shared/locales/ko.d.ts +389 -0
- package/dist/shared/locales/ko.js +443 -0
- package/dist/shared/locales/ko.js.map +1 -0
- package/dist/shared/mask.d.ts +6 -0
- package/dist/shared/mask.js +28 -0
- package/dist/shared/mask.js.map +1 -0
- package/dist/shared/notify.d.ts +15 -0
- package/dist/shared/notify.js +20 -0
- package/dist/shared/notify.js.map +1 -0
- package/dist/shared/paths.d.ts +42 -0
- package/dist/shared/paths.js +83 -0
- package/dist/shared/paths.js.map +1 -0
- package/dist/src-adapters/index.d.ts +8 -0
- package/dist/src-adapters/index.js +6 -0
- package/dist/src-adapters/index.js.map +1 -0
- package/dist/src-adapters/markdown.d.ts +80 -0
- package/dist/src-adapters/markdown.js +794 -0
- package/dist/src-adapters/markdown.js.map +1 -0
- package/dist/src-adapters/source.d.ts +33 -0
- package/dist/src-adapters/source.js +3 -0
- package/dist/src-adapters/source.js.map +1 -0
- package/dist/src-adapters/telegram.d.ts +48 -0
- package/dist/src-adapters/telegram.js +412 -0
- package/dist/src-adapters/telegram.js.map +1 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 qwertygeon
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<!-- 언어: [English](README.md) | **한국어** -->
|
|
2
|
+
|
|
3
|
+
# ADDE — Ai Driven Development Engine
|
|
4
|
+
|
|
5
|
+
_[English](README.md) | 한국어_
|
|
6
|
+
|
|
7
|
+
> ⚠️ **상태: 초기 개발.** ACP 백엔드 + Telegram/마크다운 소스 어댑터 동작(PoC 수직 슬라이스). API 변동 가능.
|
|
8
|
+
|
|
9
|
+
ADDE 는 **AI CLI**(Claude Code / Codex 등)를 **채널**(Telegram / 마크다운 노트(예: Obsidian); Discord 보류)에서 원격 구동하는 게이트웨이입니다. AI 가 개발 작업을 수행하고, 사람은 채팅으로 지시·승인·관찰합니다.
|
|
10
|
+
|
|
11
|
+
## 이럴 때 씁니다
|
|
12
|
+
|
|
13
|
+
- 자리를 비운 사이 폰(Telegram)이나 노트(Obsidian)에서 프로젝트별 AI 에게 **지시·권한 승인·결과 확인**을 하고 싶을 때.
|
|
14
|
+
- 여러 프로젝트를 각각의 작업 폴더에 묶어(레인) **동시에** 원격 운용하고 싶을 때.
|
|
15
|
+
- 모든 도구 실행에 **사람의 승인 게이트**(기본 fail-closed)를 두고 싶을 때.
|
|
16
|
+
|
|
17
|
+
> ⚠️ **데이터 흐름 주의**: 보낸 지시·코드·AI 응답은 AI 엔진 제공자(ACP→Claude/Codex 등)와 채널 인프라(Telegram)를 거칩니다. 마크다운 소스를 쓰면 승인·출력 노트가 **동기 vault(Obsidian Sync·iCloud 등)로 복제**됩니다 — 민감 프로젝트의 노트 배치 주의는 [마크다운 가이드 — 민감 정보 노출](docs/markdown.ko.md#동기화-vault-와-민감-정보-노출)을 먼저 읽으세요.
|
|
18
|
+
|
|
19
|
+
## 빠른 시작
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npm i -g adde-acp # 전역 설치
|
|
23
|
+
adde init # 가이드 설정 (환경 점검 + 짧은 별칭 + 첫 레인 생성)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`adde init` 은 `doctor`(환경 점검) → 짧은 별칭(`ad`/`add`) 설치(옵트인) → 대화형 레인 생성을 한 흐름으로 안내합니다. 수동 설정은 [시작하기](docs/getting-started.ko.md) 참조.
|
|
27
|
+
|
|
28
|
+
## 사용자 문서
|
|
29
|
+
|
|
30
|
+
- [시작하기](docs/getting-started.ko.md) — 설치·레인 설정·기동·상태/진단·프로젝트 폴더 매핑
|
|
31
|
+
- [Telegram 가이드](docs/telegram.ko.md) — 봇 생성·토큰·기동 단계별
|
|
32
|
+
- [마크다운 가이드](docs/markdown.ko.md) — 노트(예: Obsidian)로 AI 구동하기(지시·응답·권한 승인 단계별)
|
|
33
|
+
- [권한 가이드](docs/permissions.ko.md) — 게이트·티어(acp/autopass)·allowlist/denylist·하드-거부·권장 설정
|
|
34
|
+
- [명령 레퍼런스](docs/commands.ko.md) · [트러블슈팅](docs/troubleshooting.ko.md)
|
|
35
|
+
|
|
36
|
+
## 핵심 설계
|
|
37
|
+
|
|
38
|
+
- **ACP 우선**: 엔진을 헤드리스 [Agent Client Protocol](https://agentclientprotocol.com) 서브프로세스로 띄우고 ADDE 가 ACP 클라이언트로 구동합니다. 지시·응답·권한·로그·사용량이 단일 이벤트 스트림으로 처리됩니다(터미널 스크래핑 없음).
|
|
39
|
+
- **엔진 독립**: `claude-code-acp`·`codex-acp` 가 같은 프로토콜을 말하므로 단일 백엔드 어댑터가 여러 엔진을 구동합니다.
|
|
40
|
+
- **레인 격리**: `(source × backend × project)` 단위의 독립 수직 스택. 입력·승인·출력이 레인 안에서 완결됩니다.
|
|
41
|
+
- **fail-closed 권한**: 모든 권한 요청을 채널 승인으로 라우팅하고, 타임아웃·오류 시 기본 deny. 레인별 옵트인 `autopass` 티어(denylist 도구만 확인, 그 외 자동 허용·전량 기록)와, 티어 무관 즉시 거부하는 **하드-거부**(`--safe-defaults` 로 sudo·rm -rf·자격증명 읽기 등 방어심화 기본 차단)도 제공합니다.
|
|
42
|
+
- **i18n(en/ko)**: CLI 출력·채널 메시지가 영어/한국어를 지원합니다. 로케일 자동 감지(`ADDE_LANG` > 시스템 로케일 `LC_ALL`/`LC_MESSAGES`/`LANG` > 기본 en) + 레인별 채널 언어(`lane add --lang`). 상세는 [명령 레퍼런스](docs/commands.ko.md)의 "언어(로케일)".
|
|
43
|
+
|
|
44
|
+
## 명령
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
adde init [<proj>] # 가이드 설정 (doctor + 짧은 별칭 + 레인 생성)
|
|
48
|
+
adde up <proj> # 프로젝트의 모든 레인을 백그라운드 데몬으로 기동 (macOS launchd)
|
|
49
|
+
adde down <proj> # 데몬 종료 — 어느 터미널에서든 동작
|
|
50
|
+
adde restart <proj> # 데몬 재기동 (down + up)
|
|
51
|
+
adde status [<proj>] [--all] [--json] # 레인 상태 (<proj> 생략 시 전 프로젝트 실행 중 집계, --all 정지 포함)
|
|
52
|
+
adde doctor [<proj>] # 환경·설정 정적 점검 (데몬 등록·파일 권한 포함)
|
|
53
|
+
adde logs <proj> <lane> [N] [--engine] # 레인 transcript(또는 --engine 시 엔진 stderr) 최근 N줄
|
|
54
|
+
adde sessions <proj> <lane> # 엔진 세션 장부 목록 (재개/초기화는 채널 명령 — commands.md)
|
|
55
|
+
adde lane add <proj> <lane> # 레인 conf 생성 (옵션: --source/--cwd/--chat-id/--root/--safe-defaults/--interactive …)
|
|
56
|
+
adde lane ls <proj> # 레인 목록
|
|
57
|
+
adde lane show <proj> <lane> # 레인 conf 출력
|
|
58
|
+
adde lane rm <proj> <lane> # 레인 conf 삭제
|
|
59
|
+
adde alias [names...] # 짧은 별칭(ad·add) 설치 — adde 실행 파일 옆에
|
|
60
|
+
adde completion <bash|zsh> # 셸 자동완성 스크립트 출력
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
레인 설정 상세는 [시작하기](docs/getting-started.ko.md#레인-설정), 전체 명령은 [명령 레퍼런스](docs/commands.ko.md)를 참조하세요.
|
|
64
|
+
|
|
65
|
+
## 설치 / 런타임
|
|
66
|
+
|
|
67
|
+
- 설치: **npm 전역 설치** `npm i -g adde-acp`. 업데이트는 `npm i -g adde-acp@latest` 후 `adde restart <proj>`(`status`/`doctor` 가 새 버전을 안내). 개발·기여는 소스 빌드(`pnpm install && pnpm build`). 상세·권한(EACCES) 안내: [시작하기](docs/getting-started.ko.md#설치).
|
|
68
|
+
- 짧은 별칭 `ad`·`add` 는 자동 설치되지 않습니다 — `adde init` 또는 `adde alias` 로 옵트인 설치합니다(전역 명령명 충돌 회피).
|
|
69
|
+
- TypeScript + Node.js LTS (>=22)
|
|
70
|
+
- **AI 엔진 ACP 어댑터 필수**(예: `@zed-industries/claude-code-acp`) — `adde doctor` 가 사전 점검합니다.
|
|
71
|
+
- macOS 1차 타깃 — `adde up`/`down`/`restart` 는 macOS launchd LaunchAgent 기반. 재부팅·로그아웃 후 자동 복구. Linux/WSL은 현재 지원 범위 밖.
|
|
72
|
+
|
|
73
|
+
## 상태 / 로드맵
|
|
74
|
+
|
|
75
|
+
- [x] 설계 (ACP 우선 재설계 완료)
|
|
76
|
+
- [x] 개발환경 스캐폴드 (TypeScript · pnpm · CI)
|
|
77
|
+
- [x] PoC (ACP 스파이크 · 권한 라우팅)
|
|
78
|
+
- [~] MVP: `markdown | telegram → claude(ACP)` 수직 슬라이스 (소스 어댑터·레인별 프로젝트 폴더 매핑 동작)
|
|
79
|
+
- [ ] Codex 백엔드 · Discord(보류) · 비-ACP CLI 스크래핑(보류)
|
|
80
|
+
|
|
81
|
+
## 라이선스 / 보안
|
|
82
|
+
|
|
83
|
+
- 라이선스: [MIT](LICENSE)
|
|
84
|
+
- 보안 취약점 보고: [SECURITY.md](SECURITY.md)
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
<sub>전신 프로젝트: [cctg](https://qwertygeon.github.io/cctg/) (Claude Code Tmux Gateway). ADDE 는 cctg 의 `claude --channels` 의존을 걷어내고 ACP 기반으로 재설계한 후속 제품입니다.</sub>
|
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<!-- Language: **English** | [한국어](README.ko.md) -->
|
|
2
|
+
|
|
3
|
+
# ADDE — Ai Driven Development Engine
|
|
4
|
+
|
|
5
|
+
_English | [한국어](README.ko.md)_
|
|
6
|
+
|
|
7
|
+
> ⚠️ **Status: early development.** ACP backend + Telegram/Markdown source adapters work (a PoC vertical slice). The API may change.
|
|
8
|
+
|
|
9
|
+
ADDE is a gateway that drives an **AI CLI** (Claude Code / Codex, etc.) remotely from a **channel** (Telegram / Markdown notes such as Obsidian; Discord on hold). The AI does the development work while you instruct, approve, and observe from chat.
|
|
10
|
+
|
|
11
|
+
## When to use it
|
|
12
|
+
|
|
13
|
+
- When you want to **instruct a per-project AI, approve its tool use, and check results** from your phone (Telegram) or notes (Obsidian) while away from the keyboard.
|
|
14
|
+
- When you want to run several projects **concurrently**, each bound to its own working directory (a "lane").
|
|
15
|
+
- When you want a **human approval gate** (fail-closed by default) on every tool execution.
|
|
16
|
+
|
|
17
|
+
> ⚠️ **Data-flow warning**: your instructions, code, and the AI's replies pass through the AI engine provider (ACP → Claude/Codex, etc.) and the channel infrastructure (Telegram). With the Markdown source, approval/output notes are **replicated by your syncing vault** (Obsidian Sync, iCloud, etc.) — for sensitive projects, read [Markdown guide — exposure of sensitive data](docs/markdown.md#syncing-vaults-and-exposure-of-sensitive-data) first.
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npm i -g adde-acp # global install
|
|
23
|
+
adde init # guided setup (environment check + short alias + first lane)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`adde init` walks you through `doctor` (environment check) → installing short aliases (`ad`/`add`, opt-in) → creating a lane interactively. For manual setup, see [Getting started](docs/getting-started.md).
|
|
27
|
+
|
|
28
|
+
## Documentation
|
|
29
|
+
|
|
30
|
+
- [Getting started](docs/getting-started.md) — install, lane config, startup, status/diagnostics, project-folder mapping
|
|
31
|
+
- [Telegram guide](docs/telegram.md) — bot creation, token, step-by-step startup
|
|
32
|
+
- [Markdown guide](docs/markdown.md) — drive the AI from notes (e.g. Obsidian): instructions, replies, approvals
|
|
33
|
+
- [Permissions guide](docs/permissions.md) — the gate, tiers (acp/autopass), allowlist/denylist, hard-deny, recommended settings
|
|
34
|
+
- [Command reference](docs/commands.md) · [Troubleshooting](docs/troubleshooting.md)
|
|
35
|
+
|
|
36
|
+
## Core design
|
|
37
|
+
|
|
38
|
+
- **ACP-first**: the engine runs as a headless [Agent Client Protocol](https://agentclientprotocol.com) subprocess and ADDE drives it as an ACP client. Instructions, replies, permissions, logs, and usage all flow through a single event stream (no terminal scraping).
|
|
39
|
+
- **Engine-agnostic**: `claude-code-acp` and `codex-acp` speak the same protocol, so a single backend adapter drives multiple engines.
|
|
40
|
+
- **Lane isolation**: each `(source × backend × project)` is an independent vertical stack. Input, approvals, and output are self-contained within a lane.
|
|
41
|
+
- **Fail-closed permissions**: every permission request is routed to the channel for approval, defaulting to deny on timeout/error. Per-lane opt-ins are also available: an `autopass` tier (auto-allow everything except the denylist, fully recorded) and a tier-independent **hard-deny** (`--safe-defaults` blocks sudo, rm -rf, credential reads, etc. as defense-in-depth).
|
|
42
|
+
- **i18n (en/ko)**: CLI output and channel messages support English and Korean. Locale is auto-detected (`ADDE_LANG` > system locale `LC_ALL`/`LC_MESSAGES`/`LANG` > default en), with a per-lane channel language (`lane add --lang`). See "Language (locale)" in the [command reference](docs/commands.md).
|
|
43
|
+
|
|
44
|
+
## Commands
|
|
45
|
+
|
|
46
|
+
```sh
|
|
47
|
+
adde init [<proj>] # guided setup (doctor + short alias + create a lane)
|
|
48
|
+
adde up <proj> # start all lanes of the project as a background daemon (macOS launchd)
|
|
49
|
+
adde down <proj> # stop the daemon — works from any terminal
|
|
50
|
+
adde restart <proj> # restart the daemon (down + up)
|
|
51
|
+
adde status [<proj>] [--all] [--json] # lane status (all running projects if <proj> omitted, --all includes stopped)
|
|
52
|
+
adde doctor [<proj>] # static environment/config checks (incl. daemon registration + file permissions)
|
|
53
|
+
adde logs <proj> <lane> [N] [--engine] # last N lines of the lane transcript (or engine stderr with --engine)
|
|
54
|
+
adde sessions <proj> <lane> # list engine sessions (resume/clear via channel commands — see commands.md)
|
|
55
|
+
adde lane add <proj> <lane> # create a lane conf (options: --source/--cwd/--chat-id/--root/--safe-defaults/--interactive …)
|
|
56
|
+
adde lane ls <proj> # list lanes
|
|
57
|
+
adde lane show <proj> <lane> # print a lane conf
|
|
58
|
+
adde lane rm <proj> <lane> # delete a lane conf
|
|
59
|
+
adde alias [names...] # install short aliases (ad, add) next to the adde binary
|
|
60
|
+
adde completion <bash|zsh> # print a shell completion script
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
For lane configuration details see [Getting started](docs/getting-started.md#lane-configuration); for the full command set see the [command reference](docs/commands.md).
|
|
64
|
+
|
|
65
|
+
## Install / runtime
|
|
66
|
+
|
|
67
|
+
- Install: **global npm install** `npm i -g adde-acp`. Update with `npm i -g adde-acp@latest` then `adde restart <proj>` (`status`/`doctor` notify you of a new version). For development/contribution, build from source (`pnpm install && pnpm build`). Details and permission (EACCES) notes: [Getting started](docs/getting-started.md#install).
|
|
68
|
+
- The short aliases `ad`/`add` are **not** installed automatically — opt in via `adde init` or `adde alias` (avoids clashing with common global command names).
|
|
69
|
+
- TypeScript + Node.js LTS (>=22)
|
|
70
|
+
- **An AI engine ACP adapter is required** (e.g. `@zed-industries/claude-code-acp`) — `adde doctor` checks for it up front.
|
|
71
|
+
- macOS is the primary target — `adde up`/`down`/`restart` are built on macOS launchd LaunchAgents, with auto-recovery after reboot/logout. Linux/WSL are out of scope for now.
|
|
72
|
+
|
|
73
|
+
## Status / roadmap
|
|
74
|
+
|
|
75
|
+
- [x] Design (ACP-first redesign complete)
|
|
76
|
+
- [x] Dev environment scaffold (TypeScript · pnpm · CI)
|
|
77
|
+
- [x] PoC (ACP spike · permission routing)
|
|
78
|
+
- [~] MVP: `markdown | telegram → claude(ACP)` vertical slice (source adapters + per-lane project-folder mapping working)
|
|
79
|
+
- [ ] Codex backend · Discord (on hold) · non-ACP CLI scraping (on hold)
|
|
80
|
+
|
|
81
|
+
## License / security
|
|
82
|
+
|
|
83
|
+
- License: [MIT](LICENSE)
|
|
84
|
+
- Report security vulnerabilities: [SECURITY.md](SECURITY.md)
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
<sub>Predecessor project: [cctg](https://qwertygeon.github.io/cctg/) (Claude Code Tmux Gateway). ADDE is the successor that removes cctg's dependency on `claude --channels` and is redesigned around ACP.</sub>
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { LanePaths } from "../../shared/paths.js";
|
|
2
|
+
import type { SessionEvent } from "../../core/transcript.js";
|
|
3
|
+
import type { PermRequest, PermResponse } from "../../gate/gate.js";
|
|
4
|
+
import type { AddePolicy } from "./perm-diff.js";
|
|
5
|
+
import { formatWarn } from "./perm-diff.js";
|
|
6
|
+
/** allowlist 자동 허용 판정 — 도구명이 레인 allowlist 에 있으면 true. */
|
|
7
|
+
export declare function shouldAutoAllow(allowlist: string[] | undefined, toolName: string): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* autopass 자동 허용 판정 — perm_tier=autopass 이고 denylist 에 걸리지 않으면 true.
|
|
10
|
+
* denylist 는 `Tool`(전체)·`Tool(glob)`(대표 인자 패턴) 을 지원하며,
|
|
11
|
+
* 매칭 도구는 false → 기존 채널 승인 게이트(fail-closed)로 폴백한다.
|
|
12
|
+
*/
|
|
13
|
+
export declare function shouldAutopass(policy: AddePolicy | undefined, toolName: string, rawInput?: unknown): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* tool_call 세션 업데이트에서 원시 도구명을 기록한다.
|
|
16
|
+
* requestPermission 의 toolCall.title 은 인자 포함 표시 문자열(예: Bash → "`rm -rf build/`")이라
|
|
17
|
+
* allowlist/denylist 매칭 키로 쓸 수 없다 — claude-code-acp 는 원시 도구명을
|
|
18
|
+
* tool_call 업데이트의 _meta.claudeCode.toolName 으로만 노출한다.
|
|
19
|
+
*/
|
|
20
|
+
export declare function recordToolName(map: Map<string, string>, update: SessionEvent): void;
|
|
21
|
+
/** 권한 요청의 원시 도구명 해석 — 맵 우선, 요청 자체의 _meta 폴백. 미해석 시 undefined. */
|
|
22
|
+
export declare function resolveToolName(map: Map<string, string>, toolCall: Record<string, unknown>): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* 자동 허용 판정 통합 — 반환 "allowlist" | "autopass" | null(채널 승인 경로).
|
|
25
|
+
* fail-closed: 도구명 미해석(undefined) 시 자동 허용하지 않는다(채널 승인 폴백).
|
|
26
|
+
* autopass 의 denylist 는 allowlist 보다 우선한다 — 매칭되면 채널 승인.
|
|
27
|
+
*/
|
|
28
|
+
export declare function decideAutoAllow(policy: AddePolicy | undefined, toolName: string | undefined, rawInput?: unknown): "allowlist" | "autopass" | null;
|
|
29
|
+
/**
|
|
30
|
+
* 방어심화 하드-거부 판정 — 티어 무관, hard_deny 매칭 시 true(즉시 거부, 채널 프롬프트 없음).
|
|
31
|
+
* 도구명 미해석(undefined)이면 판정 불가 → false(채널 승인 경로로; 자동허용도 fail-closed 로 차단됨).
|
|
32
|
+
* autopass denylist("물어봄")보다 강하며 자동허용 판정보다 먼저 평가되어야 한다.
|
|
33
|
+
*/
|
|
34
|
+
export declare function isHardDenied(policy: AddePolicy | undefined, toolName: string | undefined, rawInput?: unknown): boolean;
|
|
35
|
+
/** 권한 게이트 결정 — 즉시 거부 / 자동 허용(경유 표기) / 채널 승인. */
|
|
36
|
+
export type PermDecision = {
|
|
37
|
+
kind: "hard_deny";
|
|
38
|
+
} | {
|
|
39
|
+
kind: "auto";
|
|
40
|
+
via: "allowlist" | "autopass";
|
|
41
|
+
} | {
|
|
42
|
+
kind: "ask";
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* 권한 결정 순서의 단일 출처(SoT) — hard-deny → 자동허용 → 채널 승인.
|
|
46
|
+
* 이 순서가 보안 핵심이다: hard_deny 는 allowlist/autopass 자동허용보다 반드시 먼저 평가되어야
|
|
47
|
+
* allowlist 에도 hard_deny 에도 있는 위험 도구(예: sudo)가 자동승인되지 않는다. 순서를 뒤집으면
|
|
48
|
+
* 그런 도구가 새므로, requestPermission 클로저는 반드시 이 함수를 통해 결정한다(순서 테스트 가능).
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolvePermDecision(policy: AddePolicy | undefined, toolName: string | undefined, rawInput?: unknown): PermDecision;
|
|
51
|
+
/** launch 옵션 — resumeSessionId 지정 시 새 세션 대신 해당 세션 복귀(session/load)를 시도한다. */
|
|
52
|
+
export interface LaunchOpts {
|
|
53
|
+
resumeSessionId?: string;
|
|
54
|
+
}
|
|
55
|
+
/** backend 가 코어에 노출하는 동사 인터페이스 (plan §인터페이스계약). */
|
|
56
|
+
export interface AcpBackend {
|
|
57
|
+
caps(): {
|
|
58
|
+
plane: "acp";
|
|
59
|
+
perm_tier: string;
|
|
60
|
+
supports_attachments: boolean;
|
|
61
|
+
acp_version: "v1";
|
|
62
|
+
};
|
|
63
|
+
/** resumed: resumeSessionId 요청이 실제로 복귀에 성공했는지(실패 시 새 세션 폴백 + false). */
|
|
64
|
+
launch(lane: string, opts?: LaunchOpts): Promise<{
|
|
65
|
+
sessionId: string;
|
|
66
|
+
resumed?: boolean;
|
|
67
|
+
}>;
|
|
68
|
+
inject(lane: string, text: string): Promise<void>;
|
|
69
|
+
subscribe(lane: string, on: (e: SessionEvent) => void): void;
|
|
70
|
+
onPermissionRequest(lane: string, handler: (req: PermRequest) => Promise<PermResponse>): void;
|
|
71
|
+
/** 레인 종료 — 엔진 child 프로세스 정리(SIGTERM→유예→SIGKILL). down/셧다운에서 호출. */
|
|
72
|
+
close(lane: string): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* 세션 리셋(/clear 등가) — 엔진 child 재기동 + 새 세션. 구독자·권한 핸들러는 보존 승계.
|
|
75
|
+
* 어댑터가 구 세션을 정리하지 않으므로 in-place 교체 대신 재기동을 쓴다(자원 청결).
|
|
76
|
+
*/
|
|
77
|
+
reset?(lane: string): Promise<{
|
|
78
|
+
sessionId: string;
|
|
79
|
+
}>;
|
|
80
|
+
/** 지정 세션으로 복귀(/resume 등가) — 재기동 + session/load. 실패 시 새 세션 폴백(resumed=false). */
|
|
81
|
+
resumeSession?(lane: string, sessionId: string): Promise<{
|
|
82
|
+
sessionId: string;
|
|
83
|
+
resumed: boolean;
|
|
84
|
+
}>;
|
|
85
|
+
}
|
|
86
|
+
interface LaneConfig {
|
|
87
|
+
paths?: LanePaths;
|
|
88
|
+
addePolicy?: AddePolicy;
|
|
89
|
+
channelWarn?: (msg: string) => void;
|
|
90
|
+
/** 레인별 엔진 작업 폴더(프로젝트 폴더 매핑). 미지정 시 process.cwd(). */
|
|
91
|
+
cwd?: string | undefined;
|
|
92
|
+
/** 권한 정규화 시 채널 표기. 미지정 시 telegram. */
|
|
93
|
+
channel?: "telegram" | "markdown" | undefined;
|
|
94
|
+
/** 채널 메시지 로케일(LaneConf.lang). 미지정 시 전역 로케일. */
|
|
95
|
+
lang?: string | undefined;
|
|
96
|
+
}
|
|
97
|
+
export declare class AcpBackendImpl implements AcpBackend {
|
|
98
|
+
private readonly adapterBin;
|
|
99
|
+
private readonly lanes;
|
|
100
|
+
private readonly laneConfigs;
|
|
101
|
+
/**
|
|
102
|
+
* relaunch → launch 로 전달되는 승계분(구독자·권한 핸들러) — launch 가 상태 생성 시 1회 소비.
|
|
103
|
+
* 인스턴스당 단일 슬롯이라 **한 impl = 한 레인** 불변식에 의존한다(supervisor 가 레인마다
|
|
104
|
+
* 별도 AcpBackendImpl 생성). 한 인스턴스가 다중 레인을 동시 relaunch 하면 승계가 레인 간
|
|
105
|
+
* 오염될 수 있으므로, 그 경우 Map<lane> 으로 키잉해야 한다.
|
|
106
|
+
*/
|
|
107
|
+
private pendingInherit;
|
|
108
|
+
constructor(adapterBin: string);
|
|
109
|
+
/**
|
|
110
|
+
* launch 전 레인별 경로·정책 설정.
|
|
111
|
+
* AcpBackend 인터페이스 계약 외부 — 구체 타입(AcpBackendImpl) 사용자만 호출.
|
|
112
|
+
*/
|
|
113
|
+
configureLane(lane: string, config: LaneConfig): void;
|
|
114
|
+
caps(): {
|
|
115
|
+
plane: "acp";
|
|
116
|
+
perm_tier: string;
|
|
117
|
+
supports_attachments: boolean;
|
|
118
|
+
acp_version: "v1";
|
|
119
|
+
};
|
|
120
|
+
launch(lane: string, opts?: LaunchOpts): Promise<{
|
|
121
|
+
sessionId: string;
|
|
122
|
+
resumed?: boolean;
|
|
123
|
+
}>;
|
|
124
|
+
/** 세션 리셋(/clear) — 재기동 + 새 세션. 구독자·핸들러 승계는 relaunch 공통부. */
|
|
125
|
+
reset(lane: string): Promise<{
|
|
126
|
+
sessionId: string;
|
|
127
|
+
}>;
|
|
128
|
+
/** 지정 세션 복귀(/resume) — 재기동 + session/load. 실패 시 새 세션 폴백(resumed=false). */
|
|
129
|
+
resumeSession(lane: string, sessionId: string): Promise<{
|
|
130
|
+
sessionId: string;
|
|
131
|
+
resumed: boolean;
|
|
132
|
+
}>;
|
|
133
|
+
/**
|
|
134
|
+
* 엔진 child 재기동 공통부 — 기존 구독자·권한 핸들러·onIdle 을 새 LaneState 로 승계한다
|
|
135
|
+
* (supervisor 배선은 launch 후 1회만 이뤄지므로 승계 없이는 재기동 시 이벤트가 유실된다).
|
|
136
|
+
* 승계는 launch 의 상태 생성 시점에 원자 적용(pendingInherit) — 등록·재부착 사이 유실 창 제거.
|
|
137
|
+
* launch 실패 시 레인은 미등록 상태로 남는다(엔진 사망) — 호출자(runControl)가 사용자에게
|
|
138
|
+
* 복구 절차(adde restart)를 명시 통지한다. 자가 재기동 감시는 후속 과제(백로그).
|
|
139
|
+
*/
|
|
140
|
+
private relaunch;
|
|
141
|
+
private fetchEngineEffective;
|
|
142
|
+
inject(lane: string, text: string): Promise<void>;
|
|
143
|
+
subscribe(lane: string, on: (e: SessionEvent) => void): void;
|
|
144
|
+
onPermissionRequest(lane: string, handler: (req: PermRequest) => Promise<PermResponse>): void;
|
|
145
|
+
/** 레인 종료 — 엔진 child 정리(SIGTERM→유예→SIGKILL) + 상태 제거. */
|
|
146
|
+
close(lane: string): Promise<void>;
|
|
147
|
+
}
|
|
148
|
+
/** formatWarn re-export — 채널 WARN 포맷 일관성. */
|
|
149
|
+
export { formatWarn };
|