deel-local-cli 0.5.0 → 0.9.0

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/README.md CHANGED
@@ -1,103 +1,428 @@
1
- # deel-local-cli
1
+ <div align="center">
2
2
 
3
- 로컬 모델·사내 게이트웨이 전용 코딩 에이전트. **외부 패키지를 하나도 쓰지 않습니다.**
3
+ # deel
4
4
 
5
- > English guide: [README.en.md](README.en.md)
5
+ **로컬 모델과 사내 게이트웨이만으로 도는 코딩 에이전트 CLI**
6
6
 
7
- **3단계(편집 신뢰성)·5단계(스킬)까지 되어 있습니다.** 실제로 파일을 읽고 고치며, PC 에 있는 스킬·명령을 찾아 씁니다.
7
+ 의존성 0개 · Node 20+ · 소스가 나가는 자리는
8
+
9
+ [English](README.en.md) · [사내 반입 안내](#사내-반입) · [문제 해결](#문제-해결)
10
+
11
+ </div>
12
+
13
+ ---
14
+
15
+ ```
16
+ ╭──────────────────────────────────────────────────────────────╮
17
+ │ deel OpenAI 호환 규격 │
18
+ │ │
19
+ │ 모델 qwen2.5-coder:7b (40k 토큰) │
20
+ │ 보냄 이 컴퓨터 안 127.0.0.1:11434 ← 여기 말고는 어디로도 안 갑니다 │
21
+ │ 연결 스트리밍 · 도구 · 추론 조절 │
22
+ │ 폴더 C:\work\myproject │
23
+ │ 이 PC 스킬 337 · 명령 127 · 플러그인 42 │
24
+ ╰──────────────────────────────────────────────────────────────╯
25
+ /help 명령 목록 /think 추론 강도 Ctrl+C 중단·끝내기
26
+
27
+ ▏myproject ▏qwen2.5-coder:7b ▏▰▰▱▱▱▱▱▱▱▱ 22% 28k/128k ▏◇ medium·절약 ▏auto
28
+ ❯ 로그 형식 통일해줘
29
+
30
+ ❊ Grep(console.log)
31
+ └ 1개 파일 · 1건
32
+ ◧ Read(src/runner.js)
33
+ └ 5줄
34
+ ◈ Edit(src/runner.js)
35
+ └ 1군데
36
+
37
+ 로그 호출을 logger 형식으로 통일했습니다. runner.js 한 군데를 고쳤습니다.
38
+
39
+ ── 4.2초 · 도구 3회 · ↑3,900 ↓180
40
+ ```
41
+
42
+ ---
43
+
44
+ ## 목차
45
+
46
+ - [왜 만들었나](#왜-만들었나)
47
+ - [빠른 시작](#빠른-시작)
48
+ - [데이터가 나가는 길](#데이터가-나가는-길)
49
+ - [로컬 모델 여러 개 쓰기](#로컬-모델-여러-개-쓰기)
50
+ - [대화 중 명령](#대화-중-명령)
51
+ - [작업 모드](#작업-모드)
52
+ - [쉬움 · 개발자](#쉬움--개발자)
53
+ - [도구](#도구)
54
+ - [한글 문서와 엑셀](#한글-문서와-엑셀)
55
+ - [스킬·플러그인](#스킬플러그인)
56
+ - [추론 강도](#추론-강도)
57
+ - [자동 압축](#자동-압축)
58
+ - [대화 이어하기](#대화-이어하기)
59
+ - [안전망](#안전망)
60
+ - [사내 반입](#사내-반입)
61
+ - [설정](#설정)
62
+ - [문제 해결](#문제-해결)
63
+ - [개발](#개발)
8
64
 
9
65
  ---
10
66
 
11
- ## 왜 의존성이 0개인가
67
+ ## 왜 만들었나
12
68
 
13
- 사내 반입 심사에서 "미승인 소프트웨어"로 걸리지 않기 위해서입니다.
14
- `package.json`의 `dependencies`가 비어 있고, Node에 원래 들어 있는 기능만 씁니다.
69
+ 사내 보안 정책이 **미승인 소프트웨어 반입**을 막으면, 코딩 에이전트 도구는 대부분 쓸 수 없습니다.
70
+ 의존성 수백 개가 딸려 오고, 설치할 스크립트가 돌고, 어디로 통신하는지 한 줄로 답할 수 없기 때문입니다.
15
71
 
72
+ deel 은 그 심사를 통과하는 것을 목표로 만들었습니다.
73
+
74
+ | | deel |
75
+ |---|---|
76
+ | 외부 의존성 | **0개** — Node 내장 기능만 |
77
+ | 설치 스크립트 | **없음** — 압축 풀고 바로 실행 |
78
+ | 소스가 나가는 자리 | **딱 한 곳** — 직접 설정한 주소 |
79
+ | 필요한 것 | Node 20 이상 |
80
+
81
+ 직접 확인하실 수 있습니다.
82
+
83
+ ```bash
84
+ npm view deel-local-cli dependencies # {}
85
+ npm view deel-local-cli scripts # install/postinstall 없음
86
+ deel audit # 심사서 전문 출력
16
87
  ```
17
- 확인 방법: npm ls → 의존성 없음
18
- cat package.json → "dependencies": {}
88
+
89
+ ---
90
+
91
+ ## 빠른 시작
92
+
93
+ ### 설치
94
+
95
+ ```bash
96
+ npm install -g deel-local-cli
97
+ ```
98
+
99
+ 설치가 싫으면 소스를 받아 그대로 쓰셔도 됩니다. `npm install` 이 필요 없습니다.
100
+
101
+ ```bash
102
+ git clone https://github.com/jysvai/deel-local-cli
103
+ node deel-local-cli/bin/deel.js
19
104
  ```
20
105
 
21
- 필요한 것은 **Node 20 이상**뿐입니다. `npm install`을 하지 않습니다.
106
+ > **주의** 디렉터리(`~`)에서 `npm install` 하지 마세요. 거기에 `node_modules` 가 생기면
107
+ > 이후 모든 npm 명령이 그 폴더를 훑어서 무관한 패키지 경고를 냅니다. `-g` 로 설치하거나 `npx` 를 쓰세요.
108
+
109
+ ### 연결 정하기
110
+
111
+ 이 PC 에 떠 있는 로컬 서버를 훑어서 고르는 방법:
112
+
113
+ ```bash
114
+ deel scan --pick
115
+ ```
116
+
117
+ 주소를 직접 넣는 방법 (사내 게이트웨이는 이쪽):
118
+
119
+ ```bash
120
+ deel setup
121
+ ```
122
+
123
+ ### 시작
124
+
125
+ 작업할 폴더에서 `deel` 을 칩니다. **그 폴더가 작업 범위가 되고, 밖의 파일은 읽지도 쓰지도 못합니다.**
126
+
127
+ ```bash
128
+ cd C:\work\myproject
129
+ deel
130
+ ```
22
131
 
23
132
  ---
24
133
 
25
- ## 대화 시작하기
134
+ ## 데이터가 나가는 길
26
135
 
27
- 작업할 폴더에서:
136
+ 코딩 에이전트는 소스 코드를 통째로 모델에 보냅니다. **그 주소가 어디인지가 전부입니다.**
137
+ 말로 보장하는 대신 코드가 막습니다 — `src/safety/network.js` 가 요청마다 확인하고,
138
+ 허용 목록에 없으면 요청을 만들지도 않습니다.
28
139
 
29
140
  ```
30
- deel # 또는 설치 없이: node <이폴더>/bin/deel.js
141
+ [A] 모델 게이트웨이 ─── 소스 코드가 나가는 유일한 길
142
+ setup 에서 정한 한 자리만. 모델을 바꾸면 이전 자리는 닫힙니다.
143
+
144
+ [B] 웹 읽기 (WebFetch) ─ 받아 오기만 하는 길
145
+ GET 만. 본문 0바이트. 사내망·로컬 주소는 거절. 다녀온 곳은 전부 기록.
146
+
147
+ [C] 플러그인 받기 ────── /plugin install 을 칠 때만 잠깐
31
148
  ```
32
149
 
33
- 폴더가 **작업 범위**가 됩니다. 밖의 파일은 읽지도 쓰지도 못합니다.
150
+ `--offline` 주면 **B C 모두 막히고 이 컴퓨터 안으로만** 다닙니다.
34
151
 
152
+ ```bash
153
+ deel --offline
35
154
  ```
36
- deel sec-llm-01 · C:\work\myproject
37
- /help 로 명령 목록. Ctrl+C 로 끝냅니다.
38
155
 
39
- 로그 형식 통일해줘
156
+ 무엇이 어디로 수 있는지는 켤 때 화면 맨 위에 늘 적혀 있습니다.
40
157
 
41
- ⏺ Grep(console.log)
42
- 1 파일 · 1건
158
+ ```
159
+ 보냄 컴퓨터 안 127.0.0.1:11434 ← 여기 말고는 어디로도 안 갑니다
160
+ ```
43
161
 
44
- Read(src/runner.js)
45
- 5줄
162
+ 수집·전송하는 것이 없습니다. 텔레메트리, 사용 통계, 오류 보고 전부 없습니다.
163
+ 대화 기록·되돌리기 이력·설정은 작업 폴더의 `.deel/` 안에만 남습니다.
46
164
 
47
- Edit(src/runner.js)
48
- 1군데
165
+ > 검증: `npm test` 의 network·web 검사 55항목. 허용되지 않은 서버에 실제로 요청이
166
+ > **한 건도 닿지 않는지**까지 진짜 서버를 띄워서 확인합니다.
49
167
 
50
- 로그 호출을 logger 형식으로 통일했습니다.
168
+ ---
169
+
170
+ ## 로컬 모델 여러 개 쓰기
171
+
172
+ 로컬 런타임은 보통 하나만 쓰지 않습니다. Ollama 로 작은 모델을 돌리면서
173
+ LM Studio 로 큰 모델을 띄워 두기도 합니다. `deel scan` 이 알려진 자리 13곳을 동시에 두드려
174
+ 전부 찾아냅니다.
51
175
 
52
- ─ 4.2초 · 도구 3회 · 180토큰
53
176
  ```
177
+ $ deel scan
178
+
179
+ ── 로컬 모델 서버 훑기 ───────────────────────────────────────────────
180
+ 127.0.0.1 의 알려진 자리 13곳을 두드립니다. 바깥으로는 나가지 않습니다.
181
+
182
+ ✓ 3곳 찾음
183
+
184
+ ◆ Ollama 127.0.0.1:11434 Ollama 규격 36ms
185
+ · qwen2.5-coder:7b 7B · 4.4GB
186
+ · llama3.2:1b 1B · 1.2GB
187
+ ◆ LM Studio 127.0.0.1:1234 OpenAI 호환 7ms
188
+ · devstral-small-2507
189
+ ◆ llama.cpp 127.0.0.1:8080 OpenAI 호환 7ms
190
+ · gemma-3-4b-it
191
+
192
+ 합계 서버 3곳 · 모델 6개
54
193
 
55
- ### 슬래시 명령
194
+ 추천 Ollama · qwen2.5-coder:7b
195
+ 코딩용 모델 · 도구 호출을 잘하는 계열
196
+ ```
56
197
 
57
- Claude Code / Codex 같은 이름을 씁니다.
198
+ 포트로 단정하지 않고 **응답을 보고** 런타임을 구분합니다 — Ollama 는 `/api/version`,
199
+ LM Studio 는 `/api/v0/models`, llama.cpp 는 `/props`. 못 알아보면 `(추정)` 이라고 밝힙니다.
200
+
201
+ | 명령 | 하는 일 |
202
+ |---|---|
203
+ | `deel scan` | 찾아서 보여주기만 |
204
+ | `deel scan --pick` | 목록에서 골라 등록 |
205
+ | `deel scan --save` | 찾은 것 전부 등록 |
206
+ | `deel scan --ports 9000,9100` | 기본 자리 말고 더 볼 포트 |
207
+ | `deel scan --host <주소>` | 기본은 `127.0.0.1` |
208
+ | `deel scan --key <키>` | 키가 필요한 로컬 서버일 때 |
209
+
210
+ 등록한 뒤에는 대화 중 `/model` 로 갈아탑니다. **대화 내용은 그대로 이어집니다.**
211
+
212
+ ---
213
+
214
+ ## 대화 중 명령
215
+
216
+ 이름은 Claude Code / Codex 관례에 맞췄습니다.
58
217
 
59
218
  | 명령 | 하는 일 |
60
219
  |---|---|
61
220
  | `/help` | 명령 목록 |
62
- | `/context` | 컨텍스트 사용량 무엇이 자리를 먹는지 |
63
- | `/compact` | 오래된 대화 줄이기 |
64
- | `/clear` | 대화 비우기 |
65
- | `/model` | 연결·모델 바꾸기 (대화는 이어짐) |
66
- | `/think off\|low\|medium\|high\|max` | 추론 강도 |
67
- | `/mode auto\|confirm\|strict` | 실행 모드 |
68
- | `/undo [턴수]` | 되돌리기 |
69
- | `/tools` | 도구 목록 |
221
+ | `/context` | 무엇이 컨텍스트를 먹고 있는지 |
222
+ | `/ctx [auto\|숫자]` | 컨텍스트 **길이** 모델에 맞춰 다시 재거나 직접 지정 |
223
+ | `/compact` | 앞선 대화를 요약해서 접기 |
224
+ | `/clear` | 대화 비우기 (연결·규칙은 유지) |
225
+ | `/model` | 연결·모델 바꾸기 |
226
+ | `/think <강도\|배분>` | 추론 강도 (`off·low·medium·high·max`) 또는 배분 (`even·save·deep`) |
227
+ | `/mode <모드>` | 승인 정책 — 얼마나 물어보나 (`auto` · `confirm` · `strict`) |
228
+ | `/work [모드]` | 작업 모드 — 무슨 일을 하는 중인가 |
229
+ | `/auto` | 다시 맡기기 — 말을 보고 알맞은 모드로 저절로 옮겨 갑니다 |
230
+ | `/code` `/plan` `/architect` `/debug` `/ask` `/orchestrator` | 작업 모드 바로 바꾸기 (그때부터 고정) |
231
+ | `/level [수준]` | 화면에 무엇을 내놓을지 (`쉬움` · `개발자`) |
232
+ | `/undo [턴수]` | 파일 변경 되돌리기 |
233
+ | `/tools` | 쓸 수 있는 도구 |
234
+ | `/skills [검색어\|all\|off]` | 스킬 보기·검색·골라 올리기 |
235
+ | `/plugin [install\|remove\|pack]` | 플러그인 관리 |
70
236
  | `/cost` | 이번 세션 사용량 |
71
237
  | `/status` | 연결 상태 |
238
+ | `/scan [save]` | 이 PC 에 떠 있는 로컬 모델 서버 훑기 (`save` 면 바로 등록) |
239
+ | `/sessions` | 이 폴더의 지난 대화 목록 |
72
240
  | `/init` | `DEEL.md` 규칙 파일 만들기 |
73
241
  | `/exit` | 끝내기 |
74
242
 
75
- ### 도구 6종
243
+ `/scan` `/sessions` 는 나가지 않고도 씁니다. 로컬 서버를 새로 켰거나 모델을
244
+ 바꿔 올렸을 때 `/scan save` → `/model` 두 번이면 대화를 이어둔 채로 갈아탑니다.
245
+
246
+ ### 도중에 멈추기
247
+
248
+ 모델이 엉뚱한 길로 가는 게 보이면 **Ctrl+C** 로 그 자리에서 끊습니다.
249
+
250
+ ```
251
+ ❯ 전체 테스트 다시 짜줘
252
+ ◧ Read test/smoke.js
253
+ ◧ Read test/loop.test.js
254
+ ^C
255
+ ⚠ 중단했습니다 (2단계까지)
256
+
257
+ ❯ ▊
258
+ ```
259
+
260
+ 끊어도 대화는 성한 채로 남습니다 — 모델이 부르겠다고 한 도구가 있으면 그 자리에
261
+ `중단했습니다` 결과를 채워 짝을 맞춥니다. 짝이 깨진 대화는 다음 요청에서 게이트웨이가
262
+ 400 으로 거절하기 때문에, 이걸 안 하면 세션 하나가 통째로 못 쓰게 됩니다.
263
+ 돌던 도구는 끝까지 돌고, **아직 시작 안 한 것은 실행되지 않습니다.**
264
+
265
+ 빈 줄에서 한 번 더 Ctrl+C 를 누르면 프로그램이 끝납니다.
266
+
267
+ 발견된 스킬의 명령은 `/<플러그인>:<이름>` 으로 부르고 `$ARGUMENTS` 가 치환됩니다.
268
+
269
+ ---
270
+
271
+ ## 작업 모드
272
+
273
+ 무슨 일을 하는 중인지에 따라 **줄 수 있는 도구와 추론 설정이 같이 바뀝니다.**
274
+ `Shift+Tab` 으로 차례로 돌리거나, 이름을 그대로 치면 됩니다.
275
+
276
+ | 모드 | 하는 일 | 파일을 고치나 | 추론 |
277
+ |---|---|---|---|
278
+ | `/auto` ◎ 종합 | **처음 값.** 말을 보고 알맞은 모드로 옮겨 간다 | 예 | 보통 (`save`) |
279
+ | `/code` ◆ 코드 | 고치고 만든다 | 예 | 보통 (`save`) |
280
+ | `/plan` ☰ 계획 | 먼저 계획만 세운다 | **아니오** | 깊게 (`deep`·high) |
281
+ | `/architect` ◈ 설계 | 구조를 짠다 | **아니오** | 깊게 (`deep`·high) |
282
+ | `/debug` ◉ 디버그 | 원인을 찾는다 | 예 | 깊게 · 단계 많이 (32) |
283
+ | `/ask` ◇ 묻기 | 설명만 한다 | **아니오** | 얕게 (`low`) |
284
+ | `/orchestrator` ❋ 총괄 | 큰 일을 쪼개서 | 예 | 단계 아주 많이 (40) |
285
+
286
+ 읽기만 하는 모드에서는 `Write`·`Edit`·`Bash` 를 **모델에게 아예 보내지 않습니다.**
287
+ "고치지 마세요" 라고 부탁하지 않습니다 — 모델은 부탁을 잊습니다. 없는 도구는 못 씁니다.
288
+
289
+ `/mode` 와 헷갈리지 마세요. 둘은 다른 축입니다.
290
+
291
+ - `/mode` — **얼마나 물어보나** (auto · confirm · strict)
292
+ - `/work` — **무슨 일을 하는 중인가** (위 일곱 가지)
293
+
294
+ `/think` 나 `/mode` 를 직접 고른 적이 있으면 그 선택이 우선합니다.
295
+ 모드가 사람이 고른 값을 덮어쓰지 않습니다.
296
+
297
+ ### 저절로 옮겨 가기 (종합 모드)
298
+
299
+ 처음에는 **종합** 으로 시작합니다. 무슨 일이 올지 모르는 상태입니다.
300
+ 한마디를 받을 때마다 그 말을 보고 알맞은 모드로 옮겨 간 다음 일합니다.
301
+
302
+ ```
303
+ ❯ 로그인이 왜 안 되지?
304
+
305
+ ◉ 디버그 (debug) 말 속에 '왜 안 되', '왜 안' 가 있어서
306
+ 다르면 /code 처럼 직접 고르세요. 그때부터는 안 바뀝니다.
307
+ ```
308
+
309
+ 옮겨 가면 그 모드의 **절차·도구·추론 설정이 전부** 따라옵니다.
310
+ "디버그 모드입니다" 라고 이름만 붙는 게 아니라, 실제로 증상→재현→가설→증거 순서를
311
+ 밟게 하고, 계획 모드에서는 `Write`·`Edit` 를 아예 안 줍니다.
312
+
313
+ | 이런 말이면 | 이 모드로 |
314
+ |---|---|
315
+ | 왜 안 돼 · 에러 · 실패 · 죽어요 · 원인 | ◉ 디버그 |
316
+ | 계획 · 순서 · 로드맵 · 먼저 잡자 | ☰ 계획 |
317
+ | 설계 · 구조를 어떻게 · 아키텍처 · 어떻게 나눌까 | ◈ 설계 |
318
+ | 뭐야? · 설명해줘 · 어떻게 동작해 · 차이가 뭐야 | ◇ 묻기 |
319
+ | 전체 · 전부 · 하나씩 · 끝까지 · 통일 | ❋ 총괄 |
320
+ | 고쳐줘 · 만들어줘 · 구현해줘 · 지워줘 | ◆ 코드 |
321
+
322
+ **애매하면 안 옮깁니다.** "음", "ㅇㅇ", "계속해줘", "아까 그거" 같은 말에는
323
+ 종합 그대로 있습니다. 1등과 2등이 비슷할 때도 안 옮깁니다 —
324
+ 잘못 옮겨서 읽기 전용 모드에 갇히면 사용자는 *왜* 막혔는지 모른 채 막힙니다.
325
+ 그래서 읽기 전용 모드(계획·설계·묻기)는 문턱을 더 높게 뒀습니다.
326
+ "설명해주고 고쳐줘" 는 묻기가 아니라 코드로 갑니다.
327
+
328
+ 옮겨 간 것은 **그 한마디에만** 붙습니다. 다음 말은 다시 처음부터 고릅니다.
329
+ 상태줄에 `~` 가 붙으면 저절로 옮겨 간 것이고, 없으면 직접 고르신 것입니다.
330
+
331
+ ```
332
+ ◎ 종합 ← 대기 중
333
+ ~◉ 디버그 ← 이번 한마디만 저절로
334
+ ◉ 디버그 ← /debug 로 직접 고름. 저절로 안 바뀝니다
335
+ ```
336
+
337
+ 직접 고르면 그때부터 **고정** 됩니다. 다시 맡기려면 `/auto` 또는 `/work 종합`.
338
+
339
+ ---
340
+
341
+ ## 쉬움 · 개발자
342
+
343
+ 처음 켠 사람에게 명령 스무 개를 들이밀면 아무것도 못 고릅니다.
344
+ 그렇다고 기능을 잠그면 쓸 만해졌을 때 막힙니다. 그래서 **보이는 것만** 나눕니다.
345
+
346
+ | | 쉬움 (기본) | 개발자 |
347
+ |---|---|---|
348
+ | `/help` 목록 | 자주 쓰는 것만 | 전부 |
349
+ | 오류 문구 | 무엇을 하면 되는지 | 원래 문구 그대로 |
350
+ | 안전 장치 | **똑같음** | **똑같음** |
351
+
352
+ `/level 개발자` 로 바꾸면 설정에 남아 다음에 켤 때도 이어집니다.
353
+
354
+ 중요한 것 두 가지입니다.
355
+
356
+ - **감춘 것도 그대로 먹습니다.** 쉬움에서 `/think high` 를 쳐도 됩니다. 목록에 안 띄울 뿐입니다.
357
+ - **초보라고 승인을 덜 받지 않습니다.** 되돌리기·작업 범위·위험 명령 차단은 두 수준이 같습니다.
358
+ 초보일수록 되돌릴 수 있어야 합니다.
359
+
360
+ ---
361
+
362
+ ## 도구
76
363
 
77
364
  이름과 인자를 Claude Code 와 같게 맞췄습니다. 그 관례로 쓰인 스킬·명령이 그대로 먹습니다.
78
365
 
79
366
  | 도구 | 하는 일 |
80
367
  |---|---|
81
- | `Read` | 파일 읽기 (줄 번호 붙음) |
368
+ | `Read` | 파일 읽기 (줄 번호 · `offset`/`limit` 지원 · **엑셀은 CSV 로 바꿔서**) |
82
369
  | `Write` | 파일 쓰기·덮어쓰기 |
83
- | `Edit` | 정확한 문자열 하나 바꾸기 |
370
+ | `Edit` | 정확한 문자열 바꾸기 (`replace_all` 지원) |
84
371
  | `Glob` | 이름 패턴으로 파일 찾기 |
85
372
  | `Grep` | 내용 정규식 검색 |
86
373
  | `Bash` | 명령 실행 |
87
374
  | `Skill` | 스킬 본문 펼쳐 읽기 (스킬이 있을 때만 모델에게 보임) |
375
+ | `WebFetch` | 웹 페이지 읽기 (읽기 전용 · `--offline` 이면 숨김) |
376
+ | `TodoWrite` | 할 일 목록 — 긴 일을 쪼개서 어디까지 했는지 화면에 띄움 |
377
+
378
+ ### 할 일 목록
379
+
380
+ 여러 단계가 걸리는 일에서 모델이 순서를 잃지 않게 하는 장치입니다.
381
+ 모델이 목록을 고칠 때마다 화면에 그대로 그려집니다.
382
+
383
+ ```
384
+ ☰ 할 일 1/3 완료 ← 방금 1개
385
+
386
+ ✓ 로그 형식 통일
387
+ ▶ 테스트 고치기
388
+ ☐ 문서 갱신
389
+ ```
390
+
391
+ `진행 중` 은 한 번에 하나만 둘 수 있습니다. 둘 이상을 진행 중으로 두려고 하면
392
+ 거절합니다 — 여러 개를 동시에 붙잡으면 무엇 하나도 안 끝나기 때문입니다.
393
+
394
+ ### 읽기만 하는 도구는 한꺼번에
395
+
396
+ 모델이 `Read` 세 개를 한 번에 부르면 세 개를 **동시에** 돌립니다.
397
+ 파일 다섯 개를 훑는 데 걸리던 시간이 한 개 읽는 시간으로 줄어듭니다.
398
+
399
+ ```
400
+ ◧ Read src/a.js ◧ Read src/b.js ◧ Read src/c.js 함께
401
+ ```
402
+
403
+ 같이 도는 것은 `Read` · `Glob` · `Grep` · `Skill` · `WebFetch` 뿐입니다.
404
+ `Write` · `Edit` · `Bash` 는 언제나 하나씩 차례로 돕니다 — 같은 파일을 두 갈래로
405
+ 고치면 되돌리기 스냅샷의 순서가 엉키고, `Bash` 는 무슨 짓을 할지 알 수 없습니다.
406
+ 결과는 동시에 끝나도 **모델이 부른 순서 그대로** 돌려줍니다. 순서가 뒤섞이면
407
+ 모델이 어느 결과가 어느 호출의 것인지 헷갈립니다.
88
408
 
89
- #### 편집이 조금 틀려도 찾아냅니다
409
+ ### 편집이 조금 틀려도 찾아냅니다
90
410
 
91
- 모델은 공백·들여쓰기·줄바꿈을 자주 틀립니다. 단계적으로 완화해 찾되, **모호하면 무조건 거부**합니다 —
92
- 엉뚱한 곳을 조용히 고치는 것이 못 찾는 것보다 훨씬 나쁘기 때문입니다.
411
+ 모델은 공백·들여쓰기·줄바꿈을 자주 틀립니다. 단계적으로 완화해 찾되,
412
+ **모호하면 무조건 거부합니다** — 엉뚱한 곳을 조용히 고치는 것이 못 찾는 것보다 훨씬 나쁩니다.
93
413
 
94
414
  ```
95
415
  정확히 일치 → 줄 끝 공백·CRLF 무시 → 들여쓰기 무시 → 모든 공백 무시
96
416
  ```
97
417
 
98
- `npm run bench` 로 잰 결과: **정확히 일치만 쓰면 20%, 지금은 100%. 엉뚱한 곳을 고친 경우 0건.**
418
+ `npm run bench` 로 잰 결과입니다.
99
419
 
100
- 찾으면 파일에서 가장 비슷한 줄을 짚어 줍니다:
420
+ | | 성공률 | 엉뚱한 곳을 고침 |
421
+ |---|---|---|
422
+ | 정확히 일치만 | 20% | 0건 |
423
+ | 지금 (단계별 완화) | **100%** | **0건** |
424
+
425
+ 못 찾으면 파일에서 가장 비슷한 줄을 짚어 줍니다.
101
426
 
102
427
  ```
103
428
  찾지 못했습니다.
@@ -108,21 +433,90 @@ Claude Code / Codex 와 같은 이름을 씁니다.
108
433
 
109
434
  ---
110
435
 
111
- ## 스킬·명령 그 PC 에 있는 것을 씁니다
436
+ ## 한글 문서와 엑셀
437
+
438
+ ### 인코딩 — 읽은 그대로 되돌려 씁니다
439
+
440
+ 사내 문서는 UTF-8 이 아닌 경우가 흔합니다. 윈도우 메모장이 오래 쓰던 완성형
441
+ (한국 CP949, 일본 CP932, 중국 GBK…) 으로 저장된 파일이 그대로 남아 있습니다.
442
+ 그걸 UTF-8 로 읽으면 통째로 깨집니다. `한글` → `�ѱ�`
443
+
444
+ 더 위험한 건 쓸 때입니다. 깨진 채로 읽고 UTF-8 로 저장하면 원본이 상합니다.
445
+ 그래서 규칙이 하나입니다 — **읽은 인코딩으로 되돌려 씁니다.**
446
+
447
+ 무엇으로 읽었는지는 **컴퓨터 설정이 아니라 파일 내용**을 보고 정합니다.
448
+ 후보마다 엄격하게 해독해 보고, 나온 글이 그 인코딩으로 쓴 진짜 글처럼
449
+ 보이는지 점수를 매깁니다. 그래서 우분투에서도, 미국 윈도우에서도, 한국
450
+ 윈도우에서도 같은 CP949 문서가 같게 읽힙니다.
451
+
452
+ ```
453
+ › Read 품의서.txt
454
+ └ 4줄 · CP949
455
+ ```
456
+
457
+ 그 인코딩에 **없는 글자**를 넣으려 하면 저장하지 않고 멈춥니다.
458
+
459
+ ```
460
+ › Edit 품의서.txt 비고 → 비고 🚀
461
+ └ 이 파일은 CP949 로 되어 있는데, 그 인코딩에 없는 글자를 넣으려 합니다: 🚀
462
+ ```
463
+
464
+ 조용히 물음표로 바꿔 저장하는 것보다 안 쓰는 편이 낫기 때문입니다.
465
+ 새로 만드는 파일은 UTF-8 입니다.
466
+
467
+ 명령 출력도 마찬가지입니다. 윈도우 명령창은 UTF-8 이 아니라, `Bash` 결과를
468
+ utf8 로 받으면 한글이 깨집니다. 바이트로 받아서 풉니다.
469
+
470
+ ### 엑셀 — CSV 로 바꿔서 읽습니다
471
+
472
+ 엑셀 파일은 글이 아니라 압축 꾸러미라, 보통은 "바이너리 파일입니다" 로 끝납니다.
473
+ 사람이 손으로 CSV 로 내보내 붙여넣어야 했습니다. `Read` 가 알아서 합니다.
474
+
475
+ ```
476
+ › Read 결재문서.xlsx
477
+ └ 시트 3개 · 128줄 · 직접 풀었습니다
478
+ ```
479
+
480
+ - **의존성 0개** 그대로입니다. xlsx 는 사실 zip 이고 그 안은 XML 이라, Node 내장 `zlib` 만으로 풉니다.
481
+ - 시트가 여럿이면 전부 줍니다. 숨긴 시트도 줍니다 (숨김이라고 표시해서).
482
+ - 날짜는 숫자가 아니라 날짜로 보여줍니다. 서식을 읽어 판단합니다.
483
+ - 수식은 식이 아니라 **계산된 값**으로 줍니다. `#REF!` 같은 오류값은 지우지 않습니다.
484
+
485
+ **암호가 걸린 파일과 옛 `.xls`** 는 엑셀에게 맡깁니다. 그것만은 직접 풀 수 없습니다.
486
+ 이때 암호를 물어봅니다.
487
+
488
+ 암호는 **아무 데도 남지 않습니다.**
489
+
490
+ - 설정 파일에 안 씁니다
491
+ - 세션 기록에 안 씁니다
492
+ - 감사기록에 안 씁니다
493
+ - 명령줄 인자로 안 넘깁니다 (작업 관리자에서 남의 명령줄이 보입니다)
494
+
495
+ 나가는 길은 자식 프로세스의 표준입력 하나뿐이고, 그 사실을 검사로 못 박아 뒀습니다.
496
+ 쓰고 나면 임시로 뽑은 내용까지 지웁니다.
497
+
498
+ > **엑셀 파일은 읽기만 됩니다.** `Edit`·`Write` 로 고치려 하면 막습니다.
499
+ > 서식·수식·차트가 든 파일을 CSV 로 왕복시키면 반드시 뭔가 잃기 때문입니다.
500
+ > 잃는 걸 알면서 쓰느니 안 쓰는 편이 낫습니다.
501
+
502
+ ---
503
+
504
+ ## 스킬·플러그인
112
505
 
113
- deel 스킬을 품고 다니지 않습니다. 켜질 때 아래를 훑어 **있는 것을 그대로** 씁니다.
506
+ **deel 스킬을 품고 다니지 않습니다.** 켜질 때 PC 를 훑어 있는 것을 그대로 씁니다.
507
+ 빈 PC 에 놓으면 0개, 스킬이 깔린 PC 에 놓으면 그 PC 의 것이 잡힙니다.
114
508
 
115
509
  ```
116
510
  프로젝트 ./.deel/skills ./.claude/skills ./.deel/commands ./.claude/commands
117
511
  사용자 ~/.deel/skills ~/.claude/skills ~/.claude/commands
118
- 플러그인 ~/.claude/plugins/** (.claude-plugin/plugin.json 이 있는 폴더)
512
+ 플러그인 ~/.claude/plugins/** ~/.deel/plugins/**
119
513
  ```
120
514
 
121
515
  Claude Code 와 같은 형식(`SKILL.md` + YAML 앞머리, `commands/*.md`, `$ARGUMENTS`)을 읽습니다.
122
516
 
123
517
  ### 3단계로 나눠 올립니다
124
518
 
125
- 전부 올리면 컨텍스트가 죽습니다. 그래서:
519
+ 전부 올리면 컨텍스트가 죽습니다.
126
520
 
127
521
  | 단계 | 무엇을 | 비용 |
128
522
  |---|---|---|
@@ -130,99 +524,237 @@ Claude Code 와 같은 형식(`SKILL.md` + YAML 앞머리, `commands/*.md`, `$AR
130
524
  | 2 | 모델이 `Skill` 도구로 고른 것의 본문만 | 필요할 때 1개씩 |
131
525
  | 3 | 본문이 가리키는 파일은 `Read` 로 | 그때 또 |
132
526
 
133
- `/context` 에서 스킬 목록이 얼마나 먹는지 바로 보입니다.
527
+ ### 플러그인 받아 오기
134
528
 
135
- ```
136
- /skills 지금 올라간 것 보기
137
- /skills <검색어> 찾아보기
138
- /skills on <검색어> 걸리는 것만 올리기
139
- /skills all | off 전부 올리기 | 내리기
140
- ```
141
-
142
- ### 슬래시 명령도 그대로
529
+ ```bash
530
+ # 온라인 기기에서
531
+ deel # 대화 시작 후
532
+ /plugin install affaan-m/ECC # git 이 있으면 clone, 없으면 tarball
533
+ /plugin pack 반입.zip # 실행 스크립트를 빼고 묶기
143
534
 
144
- 찾은 명령은 `/<플러그인>:<이름>` 으로 부릅니다. `$ARGUMENTS` 가 치환됩니다.
145
-
146
- ```
147
- › /ecc:code-review src/app.js
148
- ⌘ ecc:code-review plugin
535
+ # 오프라인 기기에서 압축만 풀면 됩니다
536
+ unzip 반입.zip -d ~/.deel/plugins/
149
537
  ```
150
538
 
539
+ `/plugin pack` 은 `.js` `.sh` `.ps1` `.py` 같은 **실행 스크립트를 빼고** 담고,
540
+ 안에 라이선스 표가 적힌 `사용안내.txt` 를 같이 넣습니다 — 그대로 반입 심사에 낼 수 있습니다.
541
+
151
542
  ### 안 넣은 것
152
543
 
153
544
  | | 이유 |
154
545
  |---|---|
155
- | hooks | 실행 스크립트라 사내 반입 심사에 걸리고, 자율 실행에 사고 경로를 늘립니다 |
546
+ | hooks | 실행 스크립트라 반입 심사에 걸리고, 자율 실행에 사고 경로를 늘립니다 |
156
547
  | 서브에이전트 | 모델 호출이 배로 늘어 게이트웨이 할당량을 먹습니다 |
157
548
  | MCP | 별도 프로토콜이라 그 자체로 하나의 프로젝트입니다 |
158
549
 
159
- ### 안전망
550
+ ---
160
551
 
161
- 승인 프롬프트 대신 **되돌릴 수 있게** 만들었습니다. 기본 모드는 `auto` — 묻지 않고 알아서 합니다.
552
+ ## 추론 강도
162
553
 
163
- | 장치 | 내용 |
164
- |---|---|
165
- | **되돌리기** | 파일을 고치기 전 항상 스냅샷. `/undo` 로 턴 단위 복구 |
166
- | **작업 범위** | 시작한 폴더 밖은 모델이 시켜도 거부 |
167
- | **위험 명령 차단** | 되돌릴 수 없는 것만 (디스크 포맷, 재귀 삭제, `--force` 푸시 등). 평범한 명령은 통과 |
168
- | **재실행 금지** | 변경성 명령은 실패해도 다시 실행하지 않음 — 두 번 돌면 사고 |
169
- | **감사 로그** | `.deel/audit.jsonl` 에 전부 기록 |
554
+ 에이전트 번의 대답은 모델을 여러 번 부릅니다. **부를 때마다 필요한 생각의 양이 다릅니다.**
555
+ 전부 세게 두면 느리고, 전부 얕게 두면 엉뚱한 길로 갑니다.
170
556
 
171
- `/mode confirm` 은 되돌릴 수 없는 명령만, `/mode strict` 는 파일 변경·명령을 전부 물어봅니다.
557
+ ```
558
+ $ /think
172
559
 
173
- ---
560
+ ── 추론 강도 ─────────────────────────────────────────────────────
561
+ 기준 medium 배분 절약 첫 판단만 세게, 이어가기는 얕게
174
562
 
175
- ## 사내망에서 진단 돌리기
563
+ 단계 강도 출력상한 언제
564
+ 첫 판단 · medium 4,096 무엇을 할지 정하는 자리
565
+ 이어가기 ↓ low 2,048 도구 결과를 읽고 다음 한 수
566
+ 막혔을 때 ↑ high 4,096 직전 도구가 오류를 냄
567
+ ```
176
568
 
177
- 압축을 풀고 폴더에서:
569
+ | 배분 | 성격 |
570
+ |---|---|
571
+ | `even` (균일) | 모든 단계 같은 강도 — 예측 가능한 대신 느림 |
572
+ | `save` (절약, 기본) | 첫 판단만 세게, 이어가기는 얕게 |
573
+ | `deep` (깊게) | 전 단계 한 칸씩 위로 — 어려운 일에만 |
574
+
575
+ ### 컨텍스트 길이는 모델에서 긁어옵니다
576
+
577
+ 이 숫자 하나가 프로그램 전체 크기를 정합니다. 한 번에 읽힐 수 있는 파일 수,
578
+ 대화가 접히는 시점, 한 번에 쓸 수 있는 답 길이가 **전부 여기서 나옵니다.**
579
+
580
+ 그래서 켤 때마다 서버에 물어봅니다. 저장된 값을 그대로 믿지 않습니다 —
581
+ 같은 이름의 모델이라도 서버에서 몇 k 로 올렸는지가 그때그때 다르고,
582
+ 그 차이는 화면에 안 뜨면 알 길이 없습니다. **그냥 조용히 작아집니다.**
178
583
 
179
584
  ```
180
- node bin/deel.js diagnose --url <게이트웨이주소> --key <키> --model <모델> --out report.txt
585
+ 모델 qwen3-coder (640k 토큰) │
586
+ ╰─────────────────────────────────────────────────────────╯
587
+ ✓ 컨텍스트를 32,768 → 655,360 로 맞췄습니다 (LM Studio에서 읽음)
181
588
  ```
182
589
 
183
- 예시:
590
+ 서버마다 이 숫자를 다른 이름, 다른 자리에 둡니다. 한 군데만 보지 않습니다.
591
+
592
+ | 서버 | 어디서 읽나 |
593
+ |---|---|
594
+ | LM Studio | `/api/v0/models` — `max_context_length` · `loaded_context_length` |
595
+ | llama.cpp | `/props` — `n_ctx` |
596
+ | vLLM | `/v1/models` — `max_model_len` |
597
+ | Ollama | `/api/show` — `<모델>.context_length` |
598
+ | 그 밖의 OpenAI 호환 | `/v1/models/<모델>` — `context_window` · `context_length` · `max_input_tokens` · `max_position_embeddings` (깊이 박혀 있어도 찾습니다) |
599
+
600
+ **모델 최대와 올려 둔 길이를 구분합니다.** LM Studio 는 655,360 까지 되는 모델을
601
+ 8,192 로 올려 둘 수 있습니다. 그 상태에서 최대치를 믿고 보내면 서버가 거절합니다.
602
+ 그래서 **실제로 쓸 값은 올려 둔 길이**로 잡고, 최대치는 따로 알려 줍니다.
184
603
 
185
604
  ```
186
- node bin/deel.js diagnose --url https://ai-gw.example.corp/v1 --key sk-xxxx --model sec-llm-01 --out report.txt
605
+ 모델은 655,360 까지 됩니다 서버에서 올린 뒤 /ctx auto
187
606
  ```
188
607
 
189
- `report.txt` 파일 하나만 가져오시면 됩니다. 색 없는 평문이라 그대로 붙여넣을 수 있습니다.
608
+ | 명령 | 하는 |
609
+ |---|---|
610
+ | `/ctx` | 지금 값과 남은 자리 |
611
+ | `/ctx auto` | 서버에 다시 물어 모델에 맞춤 |
612
+ | `/ctx 655360` | 직접 지정 (`640k` · `128k` · `1m` 도 됩니다) |
613
+ | `/ctx out 32k` | 한 번에 받을 **답 길이** 상한 — 컨텍스트와 다른 축 |
614
+ | `deel --ctx 655360` | 켤 때부터 이 값으로 (긁어오기를 건너뜁니다) |
615
+
616
+ **`k` 는 1024 입니다.** 컨텍스트 길이는 전부 2의 거듭제곱이라 그래야 아귀가 맞습니다 —
617
+ 655,360 은 `655k` 가 아니라 `640k`, 131,072 는 `131k` 가 아니라 `128k` 입니다.
618
+ 화면에 뜨는 표기와 `/ctx` 가 받는 단위가 같아서, 보이는 대로 쳐도 같은 값이 됩니다.
619
+
620
+ **출력 상한은 고정 숫자가 아닙니다.** 모델 컨텍스트와 지금 찬 양에서 매번 계산합니다 —
621
+ 남은 자리의 몇 %를 이 단계에 내줄지가 배분입니다.
622
+
623
+ | 모델 | 첫 판단 | 이어가기 | 막혔을 때 |
624
+ |---|---|---|---|
625
+ | 2k 로컬 | 554 | 512 | 554 |
626
+ | 8k 로컬 | 2,007 | 1,003 | 2,007 |
627
+ | 40k (qwen3) | 11,688 | 5,844 | 11,688 |
628
+ | 128k 게이트웨이 | 16,384 | 16,384 | 16,384 |
629
+ | 128k 인데 80% 참 | 7,680 | 3,840 | 7,680 |
630
+
631
+ 컨텍스트가 차오르면 상한도 같이 줄어듭니다. 4k 모델에 4096 을 주면 입력 자리가 안 남기 때문입니다.
632
+ 더 필요하면 프로필에 `maxTokens` 를 적어 올릴 수 있습니다.
190
633
 
191
- ### 키를 파일에 남기고 싶으면
634
+ 아끼다 대답이 잘리면 **그 단계만 상한을 풀어 자동으로 다시 부릅니다.**
635
+ 잘린 채로 넘어가면 도구 호출이 반토막 나서 조용히 실패하기 때문입니다.
636
+
637
+ ---
638
+
639
+ ## 자동 압축
640
+
641
+ 컨텍스트가 80% 차면 앞선 대화를 **요약해서 접고 계속 이어 갑니다.**
642
+ 그냥 잘라내면 모델이 하던 일을 잊고, 파일을 다시 읽고, 이미 고친 곳을 또 고칩니다.
192
643
 
193
644
  ```
194
- set DEEL_API_KEY=sk-xxxx
195
- node bin/deel.js diagnose --url https://ai-gw.example.corp/v1 --model sec-llm-01 --out report.txt
645
+ 대화 44개를 요약으로 접었습니다 — 10,399 → 3,170 토큰 (70% 줄어듦)
196
646
  ```
197
647
 
198
- 환경변수가 설정 파일보다 우선합니다.
648
+ 요약은 목표 / 한 일 / 알아낸 것 / 정한 것 / 남은 일 다섯 항목으로 남습니다.
649
+ 접을 때 **도구 호출과 그 결과가 갈라지지 않는 자리**를 골라 자릅니다 — 갈라지면 서버가 400 을 냅니다.
650
+ 요약 요청이 실패하면 옛 방식(그냥 줄이기)으로 물러서고 멈추지 않습니다.
651
+
652
+ `/compact` 로 직접 접을 수도 있습니다.
199
653
 
200
654
  ---
201
655
 
202
- ## 대화형으로 설정하기
656
+ ## 대화 이어하기
657
+
658
+ 터미널을 실수로 닫거나 컴퓨터가 재부팅돼도 하던 대화를 그대로 이어 받습니다.
659
+ 오간 내용은 **메시지 하나가 끝날 때마다 바로** `.deel/sessions/` 에 적히기 때문에,
660
+ 도중에 죽어도 그 직전까지는 남습니다.
203
661
 
204
662
  ```
205
- node bin/deel.js setup
663
+ $ deel sessions
664
+
665
+ ── 이 폴더의 대화 ──────────────────────────────────────────────
666
+ ● 20260824-090200 방금 1턴 devstral-small-2507
667
+ 테스트 깨진 거 고쳐줘
668
+ · 20260824-084500 2시간 전 2턴 qwen2.5-coder:7b
669
+ src/a.js 의 로그를 logger 로 바꿔줘
206
670
  ```
207
671
 
208
- 이름 주소 키를 물어보고, 붙어보고, 모델 목록을 띄워 고르게 한 뒤,
209
- 진단까지 돌리고 저장합니다. 저장 위치는 `~/.deel/config.json`입니다.
672
+ | 명령 | 하는 |
673
+ |---|---|
674
+ | `deel --continue` | 이 폴더에서 가장 최근 대화 이어하기 |
675
+ | `deel --resume <id>` | 골라서 이어하기 |
676
+ | `deel sessions` | 남아 있는 대화 목록 |
677
+ | `deel sessions --rm <id>` | 하나 지우기 |
678
+
679
+ 한 줄에 메시지 하나씩 쓰는 `jsonl` 이라, 쓰다가 전원이 나가도 마지막 줄만 잃습니다.
680
+ 이어받은 대화는 도구 호출과 그 결과의 짝까지 그대로 살아 있어 바로 이어서 일할 수 있습니다.
681
+ 30일이 지나고 최근 30개 밖인 것은 자동으로 정리합니다.
682
+
683
+ 저장 위치는 작업 폴더의 `.deel/sessions/` 이고, `.gitignore` 에 `.deel/` 이 들어 있어
684
+ 깃에 올라가지 않습니다.
685
+
686
+ ---
687
+
688
+ ## 안전망
689
+
690
+ 승인 프롬프트 대신 **되돌릴 수 있게** 만들었습니다. 기본 모드 `auto` 는 묻지 않고 알아서 합니다.
691
+
692
+ | 장치 | 내용 |
693
+ |---|---|
694
+ | **되돌리기** | 파일을 고치기 전 항상 스냅샷. `/undo` 로 턴 단위 복구 |
695
+ | **작업 범위** | 시작한 폴더 밖은 모델이 시켜도 거부 |
696
+ | **위험 명령 차단** | 되돌릴 수 없는 것만 (디스크 포맷, 재귀 삭제, `--force` 푸시 등) |
697
+ | **재실행 금지** | 변경성 명령은 실패해도 다시 실행하지 않음 — 두 번 돌면 사고 |
698
+ | **중단** | Ctrl+C 로 도중에 끊어도 대화가 성한 채로 남음 |
699
+ | **감사 로그** | `.deel/audit.jsonl` 에 전부 기록 |
700
+
701
+ | 모드 | 언제 물어보나 |
702
+ |---|---|
703
+ | `auto` (기본) | 안 물어봄. 되돌리기가 안전망 |
704
+ | `confirm` | 되돌릴 수 없는 명령만 |
705
+ | `strict` | 파일 변경·명령 전부 |
706
+
707
+ 되돌리기 이력은 파일 내용을 통째로 담기 때문에 큰 파일을 여러 번 고치면 금방 커집니다.
708
+ 32MB 를 넘으면 **최근 50턴만 남기고** 오래된 것을 버립니다. 방금 한 일은 언제나
709
+ 되돌릴 수 있고, 지금 이력이 얼마나 되는지는 `/status` 에서 봅니다.
710
+
711
+ ---
712
+
713
+ ## 사내 반입
714
+
715
+ 심사서와 소스를 zip 하나로 묶습니다.
210
716
 
211
- 이후에는:
717
+ ```bash
718
+ deel pack --out deel-반입.zip
719
+ ```
212
720
 
213
721
  ```
214
- node bin/deel.js 연결 상태 보기
215
- node bin/deel.js diagnose 저장된 연결로 진단 다시 돌리기
722
+ ── 반입 묶음 ───────────────────────────────────────────────────
723
+ deel-반입.zip
724
+ 39개 파일 · 100.2KB
725
+
726
+ 의존성 0개
727
+ 설치 스크립트 없음
728
+ 외부 import 0건
729
+ 네트워크 호출 3곳 (설정한 주소로만)
730
+ 포트 열기 없음
216
731
  ```
217
732
 
218
- ---
733
+ zip 안에 들어가는 `반입심사서.txt` 에는 이런 것이 적힙니다.
734
+
735
+ - 의존성 목록과 소스의 외부 `import` (0건인지)
736
+ - `preinstall` / `install` / `postinstall` / `prepare` 유무
737
+ - **소스를 훑어 찾은 네트워크·외부 명령 호출 자리 전부** (파일:줄 번호)
738
+ - 나가는 길 세 갈래 설명
739
+ - 파일별 SHA-256 (`certutil -hashfile` 로 검증 가능)
740
+
741
+ 손으로 적지 않고 코드가 소스를 훑어서 만듭니다 — 손으로 적으면 언젠가 사실과 어긋납니다.
742
+ 묶지 않고 내용만 보려면 `deel audit`.
219
743
 
220
- ## 무엇을 검사하는가
744
+ ### 사내 게이트웨이 진단
745
+
746
+ 압축을 푼 폴더에서:
747
+
748
+ ```bash
749
+ node bin/deel.js diagnose --url <게이트웨이주소> --key <키> --model <모델> --out report.txt
750
+ ```
751
+
752
+ `report.txt` 하나만 가져오시면 됩니다. 색 없는 평문입니다.
221
753
 
222
754
  | 검사 | 왜 보는가 |
223
755
  |---|---|
224
756
  | 기본 대화 | 주소·키·모델 이름이 맞는지 |
225
- | 시스템 메시지 | 규칙(DEEL.md)과 스킬이 먹는지 |
757
+ | 시스템 메시지 | 규칙(`DEEL.md`)과 스킬이 먹는지 |
226
758
  | 스트리밍 | 화면이 한 글자씩 흐를 수 있는지 |
227
759
  | **도구 호출** | **파일을 읽고 고칠 수 있는지 — 가장 중요** |
228
760
  | **도구 결과 되돌리기** | **여러 턴이 이어지는지 — 에이전트 루프의 전제** |
@@ -230,18 +762,15 @@ node bin/deel.js diagnose 저장된 연결로 진단 다시 돌리기
230
762
  | 추론 강도 조절 | `/think` 가 모델 층에서 먹는지 |
231
763
  | 컨텍스트 길이 | 파일을 몇 개까지 한 번에 읽힐 수 있는지 |
232
764
 
233
- 마지막에 **판정**이 나옵니다.
234
-
235
- | 판정 | 뜻 |
236
- |---|---|
237
- | 준비됨 | 에이전트 루프를 그대로 올릴 수 있음 |
238
- | 제한적 | 돌아가지만 편집 신뢰성 보강이 필요 |
239
- | 막힘 | 도구 호출이 안 됨 — 게이트웨이 설정을 확인해야 함 |
240
- | 연결실패 | 주소·키·인증서·프록시 문제 |
765
+ 판정은 **준비됨 · 제한적 · 막힘 · 연결실패** 넷 중 하나로 나옵니다.
241
766
 
242
767
  ---
243
768
 
244
- ## 붙는 서버
769
+ ## 설정
770
+
771
+ `~/.deel/config.json` 에 저장됩니다. 프로젝트 폴더에 `.deel/config.json` 이 있으면 그쪽이 우선입니다.
772
+
773
+ ### 붙는 서버
245
774
 
246
775
  주소만 넣으면 규격을 알아서 찾습니다.
247
776
 
@@ -250,13 +779,43 @@ node bin/deel.js diagnose 저장된 연결로 진단 다시 돌리기
250
779
  | 사내 AI 게이트웨이 (OpenAI 호환) | `https://ai-gw.example.corp/v1` |
251
780
  | Ollama | `http://localhost:11434` |
252
781
  | LM Studio | `http://localhost:1234/v1` |
253
- | vLLM · LiteLLM | `http://호스트:포트/v1` |
782
+ | llama.cpp · vLLM · LiteLLM | `http://호스트:포트/v1` |
783
+
784
+ 인증도 자동으로 맞춥니다 — `Authorization: Bearer` → `x-api-key` → `api-key`(Azure 계열) → 인증 없음.
254
785
 
255
- 인증 방식도 자동으로 맞춥니다 — `Authorization: Bearer`, `x-api-key`, `api-key`(Azure 계열), 인증 없음 순으로 시도합니다.
786
+ ### 환경변수
787
+
788
+ | 변수 | 쓰임 |
789
+ |---|---|
790
+ | `DEEL_API_KEY` | 키를 파일에 안 남기고 싶을 때 (파일보다 우선) |
791
+ | `DEEL_KEY_<프로필ID>` | 프로필별 키 |
792
+ | `NODE_EXTRA_CA_CERTS` | 사내 인증서를 쓰는 게이트웨이 |
793
+ | `HTTPS_PROXY` | 프록시를 거쳐야 할 때 |
794
+ | `DEEL_DEBUG=1` | 자세한 오류 |
795
+ | `NO_COLOR` | 색 끄기 |
796
+
797
+ ### 실행 옵션
798
+
799
+ ```bash
800
+ deel --root <폴더> 작업 범위. 기본은 지금 폴더
801
+ deel --mode <모드> auto(기본) / confirm / strict
802
+ deel --work <모드> auto(기본·종합) / code / plan / architect / debug / ask / orchestrator
803
+ deel --level <수준> 쉬움 / 개발자
804
+ deel --think <강도> off / low / medium(기본) / high / max
805
+ deel --effort <배분> even / save(기본) / deep
806
+ deel --offline 이 컴퓨터 밖으로 아무것도 안 보냄
807
+ deel --continue 가장 최근 대화 이어하기
808
+ deel --resume <id> 골라서 이어하기
809
+ ```
810
+
811
+ ### 프로젝트 규칙
812
+
813
+ 작업 폴더에 `DEEL.md` · `CLAUDE.md` · `AGENTS.md` 중 하나가 있으면 읽어서 규칙으로 씁니다.
814
+ `/init` 으로 틀을 만들 수 있습니다.
256
815
 
257
816
  ---
258
817
 
259
- ## 연결이 안 될 때
818
+ ## 문제 해결
260
819
 
261
820
  | 증상 | 확인할 것 |
262
821
  |---|---|
@@ -264,59 +823,95 @@ node bin/deel.js diagnose 저장된 연결로 진단 다시 돌리기
264
823
  | `연결이 거부되었습니다` | 서버가 꺼져 있거나 포트가 다름 |
265
824
  | `인증서 문제` | `set NODE_EXTRA_CA_CERTS=C:\경로\사내CA.pem` |
266
825
  | 프록시를 거쳐야 함 | `set HTTPS_PROXY=http://프록시:포트` |
267
- | 401 / 403 | 키가 틀렸거나 인증 헤더 형식이 다름 (진단이 4가지를 자동 시도합니다) |
268
-
269
- 자세한 오류를 보려면 `set DEEL_DEBUG=1`.
826
+ | 401 / 403 | 키가 틀렸거나 인증 헤더 형식이 다름 (4가지를 자동 시도합니다) |
827
+ | `허용되지 않은 주소입니다` | 자물쇠가 막은 것. 정상입니다 — `/model` 로 연결을 고르세요 |
828
+ | 도구 호출이 안 먹음 | `deel diagnose` 로 판정을 보세요. 작은 모델(1B~3B)은 자주 못 합니다 |
829
+ | 대답이 비어 있음 | 생각을 많이 하는 모델입니다. `/think low` 로 낮춰 보세요 |
830
+ | `deel scan` 이 0곳 | 로컬 서버가 꺼져 있거나 다른 포트 — `--ports` 로 지정 |
270
831
 
271
832
  ---
272
833
 
273
- ## 폴더 구조
834
+ ## 개발
274
835
 
275
- ```
276
- bin/deel.js 진입점
277
- src/
278
- ui/ 색·한글 폭·입력·스피너
279
- config.js 연결 프로필 저장/읽기
280
- backend/http.js HTTP + 인증 방식 4종
281
- backend/detect.js 규격·인증 자동 판별
282
- backend/adapter.js OpenAI/Ollama 차이 흡수 + 스트리밍 파서
283
- backend/probe.js 진단 검사 8종
284
- tools/index.js 도구 6종
285
- tools/fsutil.js glob·파일 훑기 (직접 구현)
286
- safety/guard.js 작업 범위 + 위험 명령 차단
287
- safety/undo.js 스냅샷·되돌리기
288
- safety/audit.js 감사 로그
289
- agent/session.js 대화 상태 + 컨텍스트 셈
290
- agent/loop.js 에이전트 루프
291
- commands.js 슬래시 명령
292
- repl.js 대화 화면
293
- report.js 진단 표 + 판정
294
- setup.js 마법사
295
- test/ 검증 (배포 zip 에서 뺀다)
836
+ ```bash
837
+ npm test 전체 검증 (254항목)
838
+ npm run verify 반입·통신 검증만
839
+ npm run bench 편집 성공률 측정
840
+ npm run demo 화면이 어떻게 보이는지 실제로 돌려 보기
841
+ npm run check 전 파일 문법 검사
296
842
  ```
297
843
 
298
- ## 검증
844
+ 검증은 **가짜 게이트웨이**를 띄워서 합니다. 실제 모델 없이 규격 그대로
845
+ 루프·스트리밍·도구 실행·되돌리기·압축을 결정적으로 확인합니다.
846
+ zip 은 진짜 `unzip` 으로, tar 는 진짜 `tar` 가 만든 것을 읽혀 교차 확인합니다.
847
+
848
+ `npm test` 는 파일을 하나씩 돌리고 **파일별 종료코드**를 표로 남깁니다.
849
+ 화면의 통과 표시가 아니라 종료코드가 CI 가 보는 값이기 때문입니다. 둘은
850
+ 갈라질 수 있습니다 — 검사를 다 통과하고도 끝낼 때 죽으면 화면은 초록인데
851
+ 종료코드는 1 입니다. 실제로 윈도우에서 그렇게 한 번 놓쳤습니다.
852
+ 첫 실패에서 멈추지 않고 끝까지 돌기 때문에, 한 번 돌리면 전부 알 수 있습니다.
299
853
 
300
854
  ```
301
- npm test 도구 20건 + 엔진 16건
302
- npm run demo 화면이 어떻게 보이는지 실제로 돌려 보기
855
+ ────────────────────────────────────────────────────────────
856
+ 검사 파일 종료코드 통과 실패 시간
857
+ ────────────────────────────────────────────────────────────
858
+ ✓ smoke.js 0 20 0 0.2초
859
+ ✗ scan.test.js 1 19 0 0.2초
860
+ ────────────────────────────────────────────────────────────
861
+
862
+ ✗ scan.test.js — 종료코드 1
863
+ 검사는 전부 통과했는데 종료코드만 1 입니다 —
864
+ 끝낼 때 남은 핸들·처리 안 된 거절 때문입니다.
303
865
  ```
304
866
 
305
- 엔진 검증은 **가짜 게이트웨이**를 띄워서 합니다. 실제 모델 없이 OpenAI 호환 규격 그대로
306
- 루프·스트리밍·도구 실행·되돌리기를 결정적으로 확인합니다.
867
+ | 검증 | 항목 | 무엇을 |
868
+ |---|---|---|
869
+ | `smoke` | 20 | 도구·작업범위·되돌리기·감사로그 |
870
+ | `loop` | 16 | 에이전트 루프·스트리밍·도구 호출 |
871
+ | `network` | 30 | 정해진 자리 밖으로 새지 않는가 |
872
+ | `web` | 25 | 웹 읽기가 읽기만 하는가 |
873
+ | `abort` | 16 | Ctrl+C 로 끊어도 대화가 성한가 |
874
+ | `parallel` | 23 | 읽기만 동시에 도는가 · 할 일 목록 |
875
+ | `compact` | 21 | 요약 압축·짝 안 깨짐·실패 시 물러섬 |
876
+ | `store` | 34 | 대화 저장·이어하기·중간에 죽어도 복구 |
877
+ | `scan` | 19 | 여러 런타임을 구분해 찾는가 |
878
+ | `plugins` | 38 | 플러그인 받기·묶기·ZIP/TAR |
879
+ | `no-bundle` | 12 | 배포 묶음에 남의 것이 안 섞였는가 · 검사 파일 위생 |
880
+ | `edit-bench` | 20건 | 편집 성공률 |
881
+
882
+ ### 폴더 구조
883
+
884
+ ```
885
+ bin/deel.js 진입점
886
+ src/
887
+ ui/ 색·한글 폭·상자·상태줄·입력
888
+ agent/loop.js 에이전트 루프
889
+ agent/session.js 대화 상태 + 컨텍스트 셈
890
+ agent/effort.js 단계별 추론 강도 배분
891
+ agent/compact.js 요약 압축
892
+ agent/store.js 대화 저장·이어하기
893
+ backend/http.js HTTP 한 겹 (바깥으로 나가는 유일한 문)
894
+ backend/detect.js 규격·인증 자동 판별
895
+ backend/adapter.js OpenAI/Ollama 차이 흡수 + 스트리밍 파서
896
+ backend/probe.js 진단 검사 8종
897
+ backend/scan.js 로컬 서버 훑기
898
+ tools/index.js 도구 9종
899
+ tools/edit-match.js 단계별 완화 편집 매칭
900
+ tools/webfetch.js 웹 읽기 (읽기 전용)
901
+ tools/todo.js 할 일 목록
902
+ skills/discover.js 그 PC 의 스킬·명령·플러그인 찾기
903
+ plugins/manage.js 플러그인 설치·삭제·묶기
904
+ pack/zip.js ZIP 쓰기 (직접 구현, 한글 이름 보존)
905
+ pack/tar.js TAR 읽기 (직접 구현)
906
+ pack/selfpack.js 반입 심사서 + 소스 묶기
907
+ safety/network.js 나가는 자리 자물쇠
908
+ safety/guard.js 작업 범위 + 위험 명령 차단
909
+ safety/undo.js 스냅샷·되돌리기
910
+ test/ 검증 (배포 묶음에서 뺀다)
911
+ ```
307
912
 
308
913
  ---
309
914
 
310
- ## 다음 단계
915
+ ## 라이선스
311
916
 
312
- | 단계 | 내용 | 상태 |
313
- |---|---|---|
314
- | 1 | 연결 설정 + 진단 | 됨 |
315
- | 2 | 엔진 — 루프 · 도구 6종 · 되돌리기 · 감사로그 | 됨 |
316
- | 4 | 화면 — 스트리밍 · 도구 배지 · 슬래시 명령 · `/context` | 됨 (2단계에서 같이) |
317
- | 7 | 추론 조절 — `/think`, `/mode`, 도구 호출 상한 | 반쯤 (모델 층·루프 층까지) |
318
- | 3 | 편집 신뢰성 — 단계별 완화 매칭 · 실패 안내 · 성공률 측정 | 됨 (20%→100%) |
319
- | 5 | 스킬·명령 발견 + 3단계 적재 | 됨 |
320
- | **6** | **플러그인 — `/plugin install` · `/plugin pack`** | **다음** |
321
- | 7 | 추론 조절 — 작업 층 (단계별 다른 모델) | 남음 |
322
- | 8 | 반입 패키징 + 외부통신 0건 검증 | 남음 |
917
+ [MIT](LICENSE)