deel-local-cli 1.4.2 → 1.4.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/README.en.md CHANGED
@@ -64,6 +64,7 @@ Zero dependencies · Node 20+ · Exactly one place your source can go
64
64
  ## Contents
65
65
 
66
66
  - [Why this exists](#why-this-exists)
67
+ - [What's different](#whats-different)
67
68
  - [Quick start](#quick-start)
68
69
  - [Where your data can go](#where-your-data-can-go)
69
70
  - [Multiple local runtimes](#multiple-local-runtimes)
@@ -99,7 +100,7 @@ This page is the **summary**. Each section links to the detail behind it.
99
100
  | [Speed and spend](docs/en/tuning.md) | Per-stage effort · the prefix cache · context length |
100
101
  | [Safety and corporate review](docs/en/safety.md) | Undo · working scope · audit log · the review package |
101
102
  | [Configuration](docs/en/config.md) · [Development](docs/en/develop.md) | Env vars · run flags · running the tests · folder layout |
102
- | [Release notes](docs/en/releases.md) | [1.4.2](docs/en/releases.md#142) · [1.4.1](docs/en/releases.md#141) · [1.4.0](docs/en/releases.md#140) · [1.3.0](docs/en/releases.md#130) · [1.2.0](docs/en/releases.md#120) |
103
+ | [Release notes](docs/en/releases.md) | [1.4.3](docs/en/releases.md#143) · [1.4.2](docs/en/releases.md#142) · [1.4.1](docs/en/releases.md#141) · [1.4.0](docs/en/releases.md#140) · [1.3.0](docs/en/releases.md#130) · [1.2.0](docs/en/releases.md#120) |
103
104
 
104
105
  ---
105
106
 
@@ -128,6 +129,82 @@ deel audit # full review sheet
128
129
 
129
130
  ---
130
131
 
132
+ ## What's different
133
+
134
+ A handful of coding agents can talk to a local model. Far fewer were
135
+ **redesigned inside for running locally.**
136
+
137
+ | | Other tools | deel |
138
+ |---|---|---|
139
+ | `/undo` | rolls back files only — the conversation still believes it happened | rewinds **the conversation too** |
140
+ | Long conversations | pay a cost cloud tools never feel, unchanged, locally | ordering designed so the prefix cache **survives** |
141
+ | Edits on small models | fail on a single whitespace mismatch | 20%→**100%** success, 0 wrong-location edits |
142
+ | Korean models | unknown until you've run them | known **in advance** from public docs |
143
+ | "Done" | says so even for what wasn't checked | `/evidence` / `/export` — **unproven items included** |
144
+ | MCP · ACP | need an SDK | `child_process` + `JSON`, nothing else |
145
+ | Compliance paperwork | hand-written, drifts from reality | **generated by scanning the source** |
146
+
147
+ <br>
148
+
149
+ #### `/undo` rewinds the conversation along with the files
150
+
151
+ Roll back only the files and the model still believes it just made that edit
152
+ — it builds the next step on a premise that no longer holds, and nothing on
153
+ screen says otherwise. deel folds the messages back in lockstep with the
154
+ files. Folding can orphan a tool call, which the server answers with a 400,
155
+ so the same pass repairs the pairing (`repairToolPairs`).
156
+
157
+ #### Fixed the hidden reason local models get slower as a conversation grows
158
+
159
+ Ollama and llama.cpp only reuse computation when a request's prefix exactly
160
+ matches the last one — change one character near the front and everything
161
+ after it, the whole conversation, gets recomputed. A cloud API never pays
162
+ this cost, so cloud-first tools have no reason to care; someone running
163
+ locally feels it compound every turn. deel pushes what can change per turn
164
+ (mode, pins) to the **end** of the prompt and sends Ollama `keep_alive: 60m`
165
+ so the front stays cached. The ordering is enforced by a test
166
+ (`test/cache.test.js`).
167
+
168
+ #### Edits actually succeed on small models
169
+
170
+ Small local models often can't reproduce the exact whitespace of the string
171
+ they're trying to edit. The internal benchmark (`npm run bench`) measured
172
+ 20% success for the old exact-match-only approach. The current approach
173
+ (stepped whitespace/indent tolerance) measures **100%** — and both approaches
174
+ land at **0** wrong-location edits. When it's ambiguous, it says so instead
175
+ of guessing.
176
+
177
+ #### Korean models are known before you've ever run them
178
+
179
+ EXAONE, HyperCLOVA X, Kanana, Midm, and Solar get whatever's verifiable from
180
+ public documentation (e.g., whether a model is a reasoning model) applied
181
+ before the first prompt. Other tools meet these models cold, and it takes a
182
+ dozen-plus turns of trial and error before anyone learns their quirks.
183
+
184
+ #### "Done" comes with a receipt, not just a claim
185
+
186
+ `/evidence` and `/export` record what wasn't verified alongside what was —
187
+ because the moment an AI coding tool is most likely to mislead someone is
188
+ exactly the moment it confidently says "done." `/export` is a self-contained
189
+ HTML file with zero outbound links, so it opens anywhere, including an
190
+ air-gapped network.
191
+
192
+ #### MCP and ACP, with no SDK
193
+
194
+ Both the Model Context Protocol and the Agent Client Protocol are just
195
+ newline-delimited JSON-RPC 2.0 over stdio. deel implements both with nothing
196
+ but `child_process` and `JSON` — proof that zero dependencies isn't a
197
+ capability given up, it's a capability that was never needed.
198
+
199
+ #### Compliance paperwork it doesn't hand-write
200
+
201
+ The import-review report, SBOM, and audit spec that `deel pack` produces are
202
+ generated **by scanning the actual source**, not typed by a person.
203
+ Hand-written paperwork eventually drifts from reality, and the moment a
204
+ reviewer catches one drifted claim, they stop trusting the rest of it.
205
+
206
+ ---
207
+
131
208
  ## Quick start
132
209
 
133
210
  ### The screen speaks English too
@@ -209,9 +286,18 @@ and never builds one for an address that is not on the allow-list.
209
286
  GET only, zero-byte body. Private/loopback addresses refused. Every visit logged.
210
287
 
211
288
  [C] Plugin fetch ─────── open only while /plugin install runs
289
+
290
+ [D] MCP servers ──────── a separate child process, someone else's program
291
+ Only starts if a human writes it into .deel/mcp.json. Off by default.
212
292
  ```
213
293
 
214
- Pass `--offline` and **both B and C are closed** traffic stays on this machine.
294
+ A, B, and C are requests deel makes itself, so each one can be filtered.
295
+ **D is different** — an MCP server is its own process; there is no way to see
296
+ what sockets it opens from the outside. So under `--offline`, instead of
297
+ filtering its requests, deel **never starts the server at all** — it doesn't
298
+ claim to have blocked what it can't actually see.
299
+
300
+ Pass `--offline` and **B, C, and D are all closed** — traffic stays on this machine.
215
301
 
216
302
  ```bash
217
303
  deel --offline
@@ -226,8 +312,9 @@ The destination is printed at the top of every session:
226
312
  Nothing is collected or transmitted. No telemetry, no usage stats, no crash reporting.
227
313
  Conversation history, undo snapshots and config live only in `.deel/` inside your working folder.
228
314
 
229
- > Verified by 55 checks in `npm test` (network + web), including bringing up a real server and
230
- > confirming that **not a single request reaches it** when it is not allow-listed.
315
+ > Verified by 123 checks in `npm test` (network + web + mcp), including bringing up a real
316
+ > server and confirming that **not a single request reaches it** when it is not allow-listed,
317
+ > and that an MCP server **never starts** under `--offline`.
231
318
 
232
319
  ---
233
320
 
@@ -893,7 +980,8 @@ so one run tells you everything.
893
980
 
894
981
  | Version | What changed |
895
982
  |---|---|
896
- | **[1.4.2](docs/en/releases.md#142)** | 1.4.1 shipped before its own security fixes this corrects that |
983
+ | **[1.4.3](docs/en/releases.md#143)** | The README explains what's different, and the review report gets its missing line |
984
+ | [1.4.2](docs/en/releases.md#142) | 1.4.1 shipped before its own security fixes — this corrects that |
897
985
  | [1.4.1](docs/en/releases.md#141) | No new features, only what was actually found and fixed — Windows abort, ReDoS, XSS |
898
986
  | [1.4.0](docs/en/releases.md#140) | deel gets a face, speaks English, and sees meaning — eleven places |
899
987
  | [1.3.0](docs/en/releases.md#130) | Evidence instead of claims, the editor instead of a terminal — six places |
package/README.md CHANGED
@@ -65,6 +65,7 @@
65
65
  ## 목차
66
66
 
67
67
  - [왜 만들었나](#왜-만들었나)
68
+ - [무엇이 다른가](#무엇이-다른가)
68
69
  - [빠른 시작](#빠른-시작)
69
70
  - [데이터가 나가는 길](#데이터가-나가는-길)
70
71
  - [로컬 모델 여러 개 쓰기](#로컬-모델-여러-개-쓰기)
@@ -100,7 +101,7 @@
100
101
  | [속도와 씀씀이](docs/ko/tuning.md) | 단계별 추론 강도 · 프리픽스 캐시 · 컨텍스트 길이 |
101
102
  | [안전망과 사내 반입](docs/ko/safety.md) | 되돌리기 · 작업 범위 · 감사기록 · 심사 서류 |
102
103
  | [설정](docs/ko/config.md) · [개발](docs/ko/develop.md) | 환경변수 · 실행 옵션 · 검사 돌리기 · 폴더 구조 |
103
- | [릴리스 노트](docs/ko/releases.md) | [1.4.2](docs/ko/releases.md#142) · [1.4.1](docs/ko/releases.md#141) · [1.4.0](docs/ko/releases.md#140) · [1.3.0](docs/ko/releases.md#130) · [1.2.0](docs/ko/releases.md#120) |
104
+ | [릴리스 노트](docs/ko/releases.md) | [1.4.3](docs/ko/releases.md#143) · [1.4.2](docs/ko/releases.md#142) · [1.4.1](docs/ko/releases.md#141) · [1.4.0](docs/ko/releases.md#140) · [1.3.0](docs/ko/releases.md#130) · [1.2.0](docs/ko/releases.md#120) |
104
105
 
105
106
  ---
106
107
 
@@ -128,6 +129,75 @@ deel audit # 심사서 전문 출력
128
129
 
129
130
  ---
130
131
 
132
+ ## 무엇이 다른가
133
+
134
+ 로컬 모델을 상대하는 코딩 에이전트는 몇 개 있습니다. 그런데 **로컬로 돌리는
135
+ 걸 전제로 속을 다시 설계한** 것은 드뭅니다.
136
+
137
+ | | 다른 도구 | deel |
138
+ |---|---|---|
139
+ | `/undo` | 파일만 되돌린다 — 대화는 그 일이 있었다고 믿는 채로 | **대화까지** 같이 되감는다 |
140
+ | 긴 대화 | 클라우드가 안 느끼는 비용을 로컬에서도 그대로 짊어진다 | 프리픽스 캐시가 **살아남게** 순서를 설계 |
141
+ | 작은 모델의 편집 | 공백 하나 틀려도 실패 | 성공률 20%→**100%**, 엉뚱한 곳 0건 |
142
+ | 국산 모델 | 겪어 보기 전엔 모른다 | 공개 문서로 **미리** 안다 |
143
+ | "다 됐습니다" | 확인 안 된 것도 됐다고 한다 | `/evidence`·`/export` — **안 된 것까지** 적는다 |
144
+ | MCP·ACP | SDK 가 필요하다 | `child_process` + `JSON` 뿐 |
145
+ | 심사 서류 | 사람이 손으로 써서 실제와 어긋난다 | **코드가 소스를 훑어서** 만든다 |
146
+
147
+ <br>
148
+
149
+ #### `/undo` 는 파일과 대화를 같이 되감습니다
150
+
151
+ 파일만 되돌리면 모델은 방금 그 편집을 했다고 계속 믿고 다음 턴을 그 위에
152
+ 쌓습니다 — 화면에는 아무 일도 없었던 것처럼 보입니다. deel 은 되돌린 만큼
153
+ 오간 메시지도 같이 접습니다. 접다가 도구 호출의 짝이 어긋나면 API 가 400 을
154
+ 내므로, 짝을 다시 맞추는 로직(`repairToolPairs`)까지 같이 돕니다.
155
+
156
+ #### 긴 대화에서 로컬 모델이 갈수록 느려지는 이유를 직접 잡았습니다
157
+
158
+ Ollama·llama.cpp 는 프롬프트 앞부분이 한 글자라도 바뀌면 그 뒤 전부를 다시
159
+ 계산합니다. 클라우드 API 는 이 비용을 안 느끼니 신경 쓸 이유가 없지만,
160
+ 로컬로 돌리는 사람에게는 대화가 길어질수록 턴마다 지연이 쌓입니다. deel 은
161
+ 매 턴 바뀔 수 있는 것(모드·핀)을 프롬프트 **맨 끝**으로 보내고, Ollama 에는
162
+ `keep_alive: 60m` 을 같이 보내 앞부분이 캐시에 그대로 남게 합니다. 이 순서는
163
+ 검사(`test/cache.test.js`)가 지킵니다.
164
+
165
+ #### 작은 모델도 편집이 실제로 성공합니다
166
+
167
+ 작은 로컬 모델은 고치려는 문자열을 공백 하나까지 완벽히 재현하지 못하는
168
+ 경우가 흔합니다. `npm run bench` 로 잰 내부 벤치마크에서, 정확히 일치만
169
+ 요구하던 옛 방식은 성공률 20% 였습니다. 지금 방식(공백·들여쓰기를 단계적으로
170
+ 완화)은 **100%** — 그러면서도 엉뚱한 곳을 고친 건수는 두 방식 다 **0건**
171
+ 입니다. 모호하면 찾지 못했다고 말할지언정 짐작해서 고치지 않습니다.
172
+
173
+ #### 국산 모델은 겪어 보기 전에 압니다
174
+
175
+ EXAONE·HyperCLOVA X·Kanana·Midm·Solar 는 공개 문서로 확인 가능한 버릇(예:
176
+ 추론형 여부)을 deel 이 미리 알고 시작합니다. 다른 도구는 이 모델들을 한
177
+ 번도 못 만나 본 채로 취급하고, 사람이 열 몇 턴을 겪어야 요령이 붙습니다.
178
+
179
+ #### "다 됐습니다" 대신 증명서를 냅니다
180
+
181
+ `/evidence` 와 `/export` 는 무엇을 바꿨는지뿐 아니라 **무엇을 확인하지
182
+ 못했는지**까지 적습니다. AI 코딩 도구가 사람을 제일 잘 속이는 순간이 자신
183
+ 있게 "됐습니다" 라고 말할 때라는 걸 알기 때문입니다. `/export` 는 바깥
184
+ 주소가 하나도 없는 자기완결 HTML 이라 폐쇄망 어디서든 열립니다.
185
+
186
+ #### MCP·ACP 를 SDK 없이 붙였습니다
187
+
188
+ Model Context Protocol 과 Agent Client Protocol 은 둘 다 표준입출력으로 줄
189
+ 단위 JSON-RPC 2.0 을 주고받는 게 전부입니다. deel 은 `child_process` 와
190
+ `JSON` 만으로 둘 다 구현했습니다 — 의존성 0개가 "기능을 뺀 결과" 가 아니라
191
+ "안 필요해서" 라는 걸 이 두 가지가 보여 줍니다.
192
+
193
+ #### 심사 서류를 손으로 안 씁니다
194
+
195
+ `deel pack` 이 만드는 반입심사서·SBOM·감사 사양은 **코드가 소스를 훑어서**
196
+ 만든 겁니다. 손으로 적은 서류는 언젠가 실제와 어긋나고, 담당자가 그걸 한 번
197
+ 발견하면 나머지 서류도 안 믿습니다.
198
+
199
+ ---
200
+
131
201
  ## 빠른 시작
132
202
 
133
203
  ### 설치
@@ -185,9 +255,17 @@ deel
185
255
  GET 만. 본문 0바이트. 사내망·로컬 주소는 거절. 다녀온 곳은 전부 기록.
186
256
 
187
257
  [C] 플러그인 받기 ────── /plugin install 을 칠 때만 잠깐
258
+
259
+ [D] MCP 서버 ─────────── 딴 자식 프로세스, 남의 프로그램
260
+ .deel/mcp.json 에 사람이 직접 적어야만 뜹니다. 기본은 꺼져 있습니다.
188
261
  ```
189
262
 
190
- `--offline` 주면 **B C 모두 막히고 컴퓨터 안으로만** 다닙니다.
263
+ A·B·C deel 직접 만드는 요청이라 하나씩 걸러낼 있습니다. **[D]
264
+ 다릅니다** — MCP 서버는 별도 프로세스라 그 안에서 무슨 소켓을 여는지 코드로
265
+ 볼 수 없습니다. 그래서 `--offline` 일 때는 요청을 거르는 대신 **그 서버
266
+ 자체를 아예 띄우지 않습니다** — 막을 수 없는 것을 막았다고 말하지 않습니다.
267
+
268
+ `--offline` 을 주면 **B·C·D 가 모두 막히고 이 컴퓨터 안으로만** 다닙니다.
191
269
 
192
270
  ```bash
193
271
  deel --offline
@@ -202,8 +280,9 @@ deel --offline
202
280
  수집·전송하는 것이 없습니다. 텔레메트리, 사용 통계, 오류 보고 전부 없습니다.
203
281
  대화 기록·되돌리기 이력·설정은 작업 폴더의 `.deel/` 안에만 남습니다.
204
282
 
205
- > 검증: `npm test` 의 network·web 검사 55항목. 허용되지 않은 서버에 실제로 요청이
206
- > **한 건도 닿지 않는지**까지 진짜 서버를 띄워서 확인합니다.
283
+ > 검증: `npm test` 의 network·web·mcp 검사 123항목. 허용되지 않은 서버에 실제로
284
+ > 요청이 **한 건도 닿지 않는지**, `--offline` MCP 서버가 **한 번도 안
285
+ > 뜨는지**까지 진짜 서버를 띄워서 확인합니다.
207
286
 
208
287
  ---
209
288
 
@@ -892,7 +971,8 @@ zip 은 진짜 `unzip` 으로, tar 는 진짜 `tar` 가 만든 것을 읽혀 교
892
971
 
893
972
  | 판 | 무엇이 바뀌었나 |
894
973
  |---|---|
895
- | **[1.4.2](docs/ko/releases.md#142)** | 1.4.1 보안 수정 전에 나갔다 그걸 바로잡는 |
974
+ | **[1.4.3](docs/ko/releases.md#143)** | README 다른지 말하고, 심사서의 빠진 줄을 채운다 |
975
+ | [1.4.2](docs/ko/releases.md#142) | 1.4.1 이 보안 수정 전에 나갔다 — 그걸 바로잡는 판 |
896
976
  | [1.4.1](docs/ko/releases.md#141) | 새 기능 없이, 실제로 찾은 것만 고친다 — 윈도우 abort·ReDoS·XSS |
897
977
  | [1.4.0](docs/ko/releases.md#140) | deel 이 제 얼굴을 갖고, 영어로도 말하고, 뜻까지 본다 — 열한 자리 |
898
978
  | [1.3.0](docs/ko/releases.md#130) | 말 대신 증거, 터미널 대신 에디터 — 여섯 자리 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deel-local-cli",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "로컬 모델·사내 게이트웨이 전용 코딩 에이전트 CLI — 외부 의존성 0개 / Zero-dependency coding agent CLI for local LLMs and private gateways",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -164,7 +164,7 @@ export function reviewSheet(a, at) {
164
164
  L.push(' 설정 파일: ~/.deel/config.json (또는 환경변수 DEEL_API_KEY)');
165
165
  L.push('');
166
166
 
167
- L.push('3-1. 나가는 길은 갈래이고 서로 섞이지 않습니다');
167
+ L.push('3-1. 나가는 길은 갈래이고 서로 섞이지 않습니다');
168
168
  L.push(줄());
169
169
  L.push(' [A] 모델 게이트웨이 — 소스 코드가 실려 나가는 유일한 길');
170
170
  L.push(' · 주소: deel setup 에서 정한 곳 딱 한 자리');
@@ -181,8 +181,14 @@ export function reviewSheet(a, at) {
181
181
  L.push(' [C] 플러그인 받기 (github) — 사용자가 /plugin install 을 칠 때만');
182
182
  L.push(' · 그 명령이 도는 동안만 열리고 끝나면 닫힙니다.');
183
183
  L.push('');
184
- L.push(' --offline 으로 켜면 [B] [C] 모두 막히고, 컴퓨터 안으로만 다닙니다.');
185
- L.push(' (검증: npm test 안의 network / web 검사 54항목이 이를 확인합니다)');
184
+ L.push(' [D] MCP 서버 자식 프로세스, 남의 프로그램');
185
+ L.push(' · .deel/mcp.json 사람이 직접 적어야만 뜹니다. 기본은 꺼져 있습니다.');
186
+ L.push(' · A·B·C 와 달리 이 서버가 안에서 무슨 소켓을 여는지는 코드로 볼 수');
187
+ L.push(' 없습니다. 그래서 요청을 거르는 대신, --offline 이면 서버 자체를');
188
+ L.push(' 아예 띄우지 않습니다.');
189
+ L.push('');
190
+ L.push(' --offline 으로 켜면 [B]·[C]·[D] 가 모두 막히고, 이 컴퓨터 안으로만 다닙니다.');
191
+ L.push(' (검증: npm test 안의 network / web / mcp 검사 123항목이 이를 확인합니다)');
186
192
  L.push('');
187
193
 
188
194
  L.push('4. 스킬·플러그인');