deel-local-cli 1.6.3 → 1.7.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.en.md CHANGED
@@ -5,10 +5,12 @@
5
5
  <img alt="deel — stays on this machine" src="docs/assets/hero-en-light.svg" width="620">
6
6
  </picture>
7
7
 
8
- ### A coding-agent CLI that runs on local models and private gateways only
8
+ ### A coding-agent CLI that runs on local models and private gateways
9
9
 
10
10
  Zero dependencies · Node 20+ · Exactly one place your source can go
11
11
 
12
+ Vendor APIs connect too — **only when you say so**
13
+
12
14
  <br>
13
15
 
14
16
  [![npm](https://img.shields.io/npm/v/deel-local-cli?logo=npm&logoColor=white&label=npm&color=cb3837)](https://www.npmjs.com/package/deel-local-cli)
@@ -18,7 +20,7 @@ Zero dependencies · Node 20+ · Exactly one place your source can go
18
20
 
19
21
  [![Node.js CI](https://img.shields.io/github/actions/workflow/status/jysvai/deel-local-cli/test.yml?branch=main&logo=github&logoColor=white&label=Node.js%20CI)](https://github.com/jysvai/deel-local-cli/actions/workflows/test.yml)
20
22
  [![CodeQL](https://img.shields.io/github/actions/workflow/status/jysvai/deel-local-cli/codeql.yml?branch=main&logo=github&logoColor=white&label=CodeQL)](https://github.com/jysvai/deel-local-cli/actions/workflows/codeql.yml)
21
- [![tests](https://img.shields.io/badge/tests-4%2C932%20passing-1a7f37?logo=checkmarx&logoColor=white)](docs/en/develop.md)
23
+ [![tests](https://img.shields.io/badge/tests-5%2C685%20passing-1a7f37?logo=checkmarx&logoColor=white)](docs/en/develop.md)
22
24
 
23
25
  [![dependencies](https://img.shields.io/badge/dependencies-0-1a7f37)](https://www.npmjs.com/package/deel-local-cli?activeTab=dependencies)
24
26
  [![ESM](https://img.shields.io/badge/ESM-Node%2020%2B-5FA04E?logo=javascript&logoColor=white)](package.json)
@@ -33,7 +35,7 @@ Zero dependencies · Node 20+ · Exactly one place your source can go
33
35
 
34
36
  ```
35
37
  ╭──────────────────────────────────────────────────────────────╮
36
- │ deel OpenAI-compatible
38
+ │ deel 1.7.0 ⌂ inside OpenAI-compatible
37
39
  │ │
38
40
  │ Model qwen2.5-coder:7b (40k tokens) │
39
41
  │ Sends to this machine 127.0.0.1:11434 ← nowhere else │
@@ -67,6 +69,7 @@ Zero dependencies · Node 20+ · Exactly one place your source can go
67
69
  - [What's different](#whats-different)
68
70
  - [Quick start](#quick-start)
69
71
  - [Where your data can go](#where-your-data-can-go)
72
+ - [Connecting a vendor API](#connecting-a-vendor-api)
70
73
  - [Multiple local runtimes](#multiple-local-runtimes)
71
74
  - [Slash commands](#slash-commands)
72
75
  - [Work modes](#work-modes)
@@ -100,7 +103,7 @@ This page is the **summary**. Each section links to the detail behind it.
100
103
  | [Speed and spend](docs/en/tuning.md) | Per-stage effort · the prefix cache · context length |
101
104
  | [Safety and corporate review](docs/en/safety.md) | Undo · working scope · audit log · the review package |
102
105
  | [Configuration](docs/en/config.md) · [Development](docs/en/develop.md) | Env vars · run flags · running the tests · folder layout |
103
- | [Release notes](docs/en/releases.md) | [1.6.1](docs/en/releases.md#161) · [1.6.0](docs/en/releases.md#160) · [1.5.8](docs/en/releases.md#158) · [1.5.7](docs/en/releases.md#157) · [1.5.6](docs/en/releases.md#156) · [1.5.5](docs/en/releases.md#155) · [1.5.4](docs/en/releases.md#154) · [1.5.3](docs/en/releases.md#153) · [1.5.2](docs/en/releases.md#152) · [1.5.1](docs/en/releases.md#151) · [1.5.0](docs/en/releases.md#150) · [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) |
106
+ | [Release notes](docs/en/releases.md) | [1.7.x](docs/en/releases/1.7.md) · [1.6.x](docs/en/releases/1.6.md) · [1.5.x](docs/en/releases/1.5.md) · [1.4.x](docs/en/releases/1.4.md) · [1.3.x](docs/en/releases/1.3.md) · [1.2.x](docs/en/releases/1.2.md) |
104
107
 
105
108
  ---
106
109
 
@@ -310,18 +313,106 @@ deel --offline
310
313
  The destination is printed at the top of every session:
311
314
 
312
315
  ```
316
+ deel 1.7.0 ⌂ inside
313
317
  Sends to this machine 127.0.0.1:11434 ← nowhere else
314
318
  ```
315
319
 
320
+ ### Three run modes
321
+
322
+ Through 1.6 the only lock was `--offline`, and **the default was open**. One
323
+ line in `.deel/config.json` pointing outside was enough. The screen did show
324
+ `↗`, but that is a *notice*, not a lock.
325
+
326
+ | Mode | How | On an external address |
327
+ |---|---|---|
328
+ | `⌂ inside` | `deel` (default) | **Asks.** Say yes once and that connection stops asking |
329
+ | `↗ outside` | `deel online` · `--online` | Does not ask |
330
+ | `⛊ sealed` | `deel offline` · `--offline` | Ignores even remembered permission (strongest) |
331
+
332
+ **Both the address and the permission are required.** Changing the address
333
+ alone does not get you out.
334
+
335
+ Local and intranet ranges (`127.x` · `10.x` · `192.168.x` · `172.16-31.x`) pass
336
+ in all three modes — `offline` does not mean "no internet," it means "nothing
337
+ leaves the company."
338
+
316
339
  Nothing is collected or transmitted. No telemetry, no usage stats, no crash reporting.
317
340
  Conversation history, undo snapshots and config live only in `.deel/` inside your working folder.
318
341
 
319
- > Verified by 123 checks in `npm test` (network + web + mcp), including bringing up a real
342
+ > Verified by 159 checks in `npm test` (network + web + mcp), including bringing up a real
320
343
  > server and confirming that **not a single request reaches it** when it is not allow-listed,
321
344
  > and that an MCP server **never starts** under `--offline`.
322
345
 
323
346
  ---
324
347
 
348
+ ## Connecting a vendor API
349
+
350
+ Local models are the default and that does not change. But "we have no GPU
351
+ in-house" and "just this one task on a bigger model" are real situations, so
352
+ vendor APIs can connect. **The modes above guard that door.**
353
+
354
+ ```bash
355
+ deel setup
356
+ ```
357
+
358
+ Instead of asking for a URL, it asks **where you're connecting**.
359
+
360
+ ```
361
+ 1. I only have a key — I'll figure out where it goes 1 blank
362
+ 2. Enter an address (corporate gateway · local) 2 blanks
363
+ 3. OpenAI (GPT) 1 blank
364
+ 4. Anthropic (Claude) 1 blank
365
+ 5. Google (Gemini) 1 blank
366
+ 6. AWS Bedrock 2 blanks
367
+ ```
368
+
369
+ Option 1 is the point — the key prefix decides which single vendor is asked.
370
+
371
+ ```
372
+ ❯ sk-ant-api03-••••
373
+ ✓ Looks like an Anthropic (Claude) key. (the key starts with sk-ant-)
374
+ It is not thrown at every vendor in turn.
375
+ ```
376
+
377
+ Probing vendors one by one would send an Anthropic key to OpenAI's server and
378
+ then to Google's. You get a 401 and stop — but **the key has already left.**
379
+ So an unrecognized key is never guessed at; you are asked.
380
+
381
+ Bedrock asks for a region — five including Seoul (`ap-northeast-2`), plus
382
+ "enter it yourself." Claude has a different wire shape, absorbed in six places
383
+ ([1.7.0 release notes](docs/en/releases/1.7.md#170)).
384
+
385
+ ### Going outside masks secrets in file contents too
386
+
387
+ While everything stayed local, text read from files was deliberately **not**
388
+ masked: mask it and the model writes the mask back into the file, destroying
389
+ your real key.
390
+
391
+ Going outside flips that trade. One `Read` puts your whole `.env` into someone
392
+ else's server log, and that cannot be undone. The other side is now handled
393
+ elsewhere — `Write`, `Append` and `Edit` refuse to write a mask back into a file.
394
+
395
+ ### You can see what it costs
396
+
397
+ ```
398
+ ❯ ─ 12.4s · 3 tools · ↑8.2k ↓1.1k · $0.0271
399
+ ```
400
+
401
+ **There is no built-in price table.** Prices change whenever a vendor decides,
402
+ and a table baked into source would have the tool confidently printing wrong
403
+ amounts six months later. Write them in `.deel/config.json` — dollars per
404
+ million tokens:
405
+
406
+ ```json
407
+ "요금": { "claude-opus-4-6": { "입력": 0, "출력": 0, "기준": "2026-09-01" } }
408
+ ```
409
+
410
+ The amount is shown with **where it came from and as of when**, and after six
411
+ months it is marked stale. Unknown means nothing is printed — a local-only
412
+ session never sees money at all.
413
+
414
+ ---
415
+
325
416
  ## Multiple local runtimes
326
417
 
327
418
  People rarely run just one. `deel scan` knocks on 13 known ports concurrently and identifies
@@ -946,7 +1037,7 @@ Stored in `~/.deel/config.json`. A `.deel/config.json` in the project folder tak
946
1037
  ## Development
947
1038
 
948
1039
  ```bash
949
- npm test Full suite (4,932 checks)
1040
+ npm test Full suite (5,685 checks)
950
1041
  npm run coverage Which lines the tests actually execute
951
1042
  npm run verify Import + network checks only
952
1043
  npm run bench Edit success rate
@@ -998,23 +1089,24 @@ so one run tells you everything.
998
1089
 
999
1090
  | Version | What changed |
1000
1091
  |---|---|
1001
- | **[1.6.1](docs/en/releases.md#161)** | The places that made a turn spin in circles the fence blocking `/dev/null` · old documents it could not read · images vanishing from files |
1002
- | **[1.6.0](docs/en/releases.md#160)** | The things that did not work on a corporate network proxy · 429 · Windows shell · 50k-file repos · PDF · clipboard paste · editor resume |
1003
- | **[1.5.8](docs/en/releases.md#158)** | A 5MB document showed 8 lines out of 919 · a regex read as a path blocked the command |
1004
- | **[1.5.7](docs/en/releases.md#157)** | Korean folders on macOS made your own files "out of scope" · paste · ESC |
1005
- | **[1.5.6](docs/en/releases.md#156)** | It asks when stuck instead of writing a question and ending the turn |
1006
- | **[1.5.5](docs/en/releases.md#155)** | A plan fills the room "only one person" was a bug, not a design |
1007
- | [1.5.4](docs/en/releases.md#154) | A day passes in the room — morning to night, a wall clock, a cold coffee |
1008
- | [1.5.3](docs/en/releases.md#153) | Three things a Mac user tripped over newline hint, office stays put, one `/motion` |
1009
- | [1.5.2](docs/en/releases.md#152) | Everything else the adversarial reviews turned upwhere the screen was lying |
1010
- | [1.5.1](docs/en/releases.md#151) | Two of the things 1.5.0 added shipped broken. This fixes them |
1011
- | [1.5.0](docs/en/releases.md#150) | Line breaks exist now, the screen got fun, and it came out lighter than before |
1012
- | [1.4.3](docs/en/releases.md#143) | The README explains what's different, and the review report gets its missing line |
1013
- | [1.4.2](docs/en/releases.md#142) | 1.4.1 shipped before its own security fixes this corrects that |
1014
- | [1.4.1](docs/en/releases.md#141) | No new features, only what was actually found and fixed Windows abort, ReDoS, XSS |
1015
- | [1.4.0](docs/en/releases.md#140) | deel gets a face, speaks English, and sees meaning eleven places |
1016
- | [1.3.0](docs/en/releases.md#130) | Evidence instead of claims, the editor instead of a terminal six places |
1017
- | [1.2.0](docs/en/releases.md#120) | So the conversation doesn't break — six places |
1092
+ | **[1.7.0](docs/en/releases/1.7.md#170)** | Local stays local; it goes out only when you say so three modes · vendor setup · automatic masking · cost |
1093
+ | [1.6.1](docs/en/releases/1.6.md#161) | The places that made a turn spin in circlesthe fence blocking `/dev/null` · old documents it could not read · images vanishing from files |
1094
+ | **[1.6.0](docs/en/releases/1.6.md#160)** | The things that did not work on a corporate network — proxy · 429 · Windows shell · 50k-file repos · PDF · clipboard paste · editor resume |
1095
+ | **[1.5.8](docs/en/releases/1.5.md#158)** | A 5MB document showed 8 lines out of 919 · a regex read as a path blocked the command |
1096
+ | **[1.5.7](docs/en/releases/1.5.md#157)** | Korean folders on macOS made your own files "out of scope" · paste · ESC |
1097
+ | **[1.5.6](docs/en/releases/1.5.md#156)** | It asks when stuckinstead of writing a question and ending the turn |
1098
+ | **[1.5.5](docs/en/releases/1.5.md#155)** | A plan fills the room — "only one person" was a bug, not a design |
1099
+ | [1.5.4](docs/en/releases/1.5.md#154) | A day passes in the roommorning to night, a wall clock, a cold coffee |
1100
+ | [1.5.3](docs/en/releases/1.5.md#153) | Three things a Mac user tripped overnewline hint, office stays put, one `/motion` |
1101
+ | [1.5.2](docs/en/releases/1.5.md#152) | Everything else the adversarial reviews turned up where the screen was lying |
1102
+ | [1.5.1](docs/en/releases/1.5.md#151) | Two of the things 1.5.0 added shipped broken. This fixes them |
1103
+ | [1.5.0](docs/en/releases/1.5.md#150) | Line breaks exist now, the screen got fun, and it came out lighter than before |
1104
+ | [1.4.3](docs/en/releases/1.4.md#143) | The README explains what's different, and the review report gets its missing line |
1105
+ | [1.4.2](docs/en/releases/1.4.md#142) | 1.4.1 shipped before its own security fixesthis corrects that |
1106
+ | [1.4.1](docs/en/releases/1.4.md#141) | No new features, only what was actually found and fixedWindows abort, ReDoS, XSS |
1107
+ | [1.4.0](docs/en/releases/1.4.md#140) | deel gets a face, speaks English, and sees meaningeleven places |
1108
+ | [1.3.0](docs/en/releases/1.3.md#130) | Evidence instead of claims, the editor instead of a terminal — six places |
1109
+ | [1.2.0](docs/en/releases/1.2.md#120) | So the conversation doesn't break — six places |
1018
1110
 
1019
1111
  What changed and why is in the **[release notes](docs/en/releases.md)**.
1020
1112
 
package/README.md CHANGED
@@ -5,10 +5,12 @@
5
5
  <img alt="deel — 이 컴퓨터 안에서만" src="docs/assets/hero-ko-light.svg" width="620">
6
6
  </picture>
7
7
 
8
- ### 로컬 모델과 사내 게이트웨이만으로 도는 코딩 에이전트 CLI
8
+ ### 로컬 모델과 사내 게이트웨이로 도는 코딩 에이전트 CLI
9
9
 
10
10
  의존성 0개 · Node 20+ · 소스가 나가는 자리는 딱 한 곳
11
11
 
12
+ 바깥 API 도 붙습니다 — **말했을 때만**
13
+
12
14
  <br>
13
15
 
14
16
  [![npm](https://img.shields.io/npm/v/deel-local-cli?logo=npm&logoColor=white&label=npm&color=cb3837)](https://www.npmjs.com/package/deel-local-cli)
@@ -18,7 +20,7 @@
18
20
 
19
21
  [![Node.js CI](https://img.shields.io/github/actions/workflow/status/jysvai/deel-local-cli/test.yml?branch=main&logo=github&logoColor=white&label=Node.js%20CI)](https://github.com/jysvai/deel-local-cli/actions/workflows/test.yml)
20
22
  [![CodeQL](https://img.shields.io/github/actions/workflow/status/jysvai/deel-local-cli/codeql.yml?branch=main&logo=github&logoColor=white&label=CodeQL)](https://github.com/jysvai/deel-local-cli/actions/workflows/codeql.yml)
21
- [![tests](https://img.shields.io/badge/tests-4%2C932%20passing-1a7f37?logo=checkmarx&logoColor=white)](docs/ko/develop.md)
23
+ [![tests](https://img.shields.io/badge/tests-5%2C685%20passing-1a7f37?logo=checkmarx&logoColor=white)](docs/ko/develop.md)
22
24
 
23
25
  [![dependencies](https://img.shields.io/badge/dependencies-0-1a7f37)](https://www.npmjs.com/package/deel-local-cli?activeTab=dependencies)
24
26
  [![ESM](https://img.shields.io/badge/ESM-Node%2020%2B-5FA04E?logo=javascript&logoColor=white)](package.json)
@@ -33,7 +35,7 @@
33
35
 
34
36
  ```
35
37
  ╭──────────────────────────────────────────────────────────────╮
36
- │ deel OpenAI 호환 규격
38
+ │ deel 1.7.0 ⌂ 이 안 OpenAI 호환 규격
37
39
  │ │
38
40
  │ 모델 qwen2.5-coder:7b (40k 토큰) │
39
41
  │ 보냄 이 컴퓨터 안 127.0.0.1:11434 ← 여기 말고는 어디로도 안 갑니다 │
@@ -68,6 +70,7 @@
68
70
  - [무엇이 다른가](#무엇이-다른가)
69
71
  - [빠른 시작](#빠른-시작)
70
72
  - [데이터가 나가는 길](#데이터가-나가는-길)
73
+ - [바깥 API 붙이기](#바깥-api-붙이기)
71
74
  - [로컬 모델 여러 개 쓰기](#로컬-모델-여러-개-쓰기)
72
75
  - [대화 중 명령](#대화-중-명령)
73
76
  - [작업 모드](#작업-모드)
@@ -101,7 +104,7 @@
101
104
  | [속도와 씀씀이](docs/ko/tuning.md) | 단계별 추론 강도 · 프리픽스 캐시 · 컨텍스트 길이 |
102
105
  | [안전망과 사내 반입](docs/ko/safety.md) | 되돌리기 · 작업 범위 · 감사기록 · 심사 서류 |
103
106
  | [설정](docs/ko/config.md) · [개발](docs/ko/develop.md) | 환경변수 · 실행 옵션 · 검사 돌리기 · 폴더 구조 |
104
- | [릴리스 노트](docs/ko/releases.md) | [1.6.1](docs/ko/releases.md#161) · [1.6.0](docs/ko/releases.md#160) · [1.5.8](docs/ko/releases.md#158) · [1.5.7](docs/ko/releases.md#157) · [1.5.6](docs/ko/releases.md#156) · [1.5.5](docs/ko/releases.md#155) · [1.5.4](docs/ko/releases.md#154) · [1.5.3](docs/ko/releases.md#153) · [1.5.2](docs/ko/releases.md#152) · [1.5.1](docs/ko/releases.md#151) · [1.5.0](docs/ko/releases.md#150) · [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) |
107
+ | [릴리스 노트](docs/ko/releases.md) | [1.7.x](docs/ko/releases/1.7.md) · [1.6.x](docs/ko/releases/1.6.md) · [1.5.x](docs/ko/releases/1.5.md) · [1.4.x](docs/ko/releases/1.4.md) · [1.3.x](docs/ko/releases/1.3.md) · [1.2.x](docs/ko/releases/1.2.md) |
105
108
 
106
109
  ---
107
110
 
@@ -274,18 +277,103 @@ deel --offline
274
277
  무엇이 어디로 갈 수 있는지는 켤 때 화면 맨 위에 늘 적혀 있습니다.
275
278
 
276
279
  ```
280
+ deel 1.7.0 ⌂ 이 안
277
281
  보냄 이 컴퓨터 안 127.0.0.1:11434 ← 여기 말고는 어디로도 안 갑니다
278
282
  ```
279
283
 
284
+ ### 실행 모드 셋
285
+
286
+ 1.6 까지는 자물쇠가 `--offline` 하나였고 **기본이 열림**이었습니다.
287
+ `.deel/config.json` 의 주소 한 줄만 바깥으로 바꾸면 그대로 나갔습니다.
288
+ 화면에 `↗` 가 뜨긴 했지만 그건 **알리는 것**이지 막는 것이 아닙니다.
289
+
290
+ | 모드 | 켜는 법 | 바깥 주소일 때 |
291
+ |---|---|---|
292
+ | `⌂ 이 안` | `deel` (처음 값) | **물어봅니다.** 한 번 허락하면 그 연결은 다음부터 안 묻습니다 |
293
+ | `↗ 바깥` | `deel online` · `--online` | 안 물어봅니다 |
294
+ | `⛊ 봉인` | `deel offline` · `--offline` | 기억해 둔 허가까지 무시합니다 (제일 셈) |
295
+
296
+ **주소와 허가가 둘 다 있어야 나갑니다.** 주소만 바꿔서는 못 나갑니다.
297
+
298
+ 로컬·사내망(`127.x` · `10.x` · `192.168.x` · `172.16~31.x`)은 셋 중 어느
299
+ 모드에서도 그냥 갑니다 — `offline` 은 「인터넷 없음」 이 아니라 「회사 밖으로
300
+ 안 나감」 입니다.
301
+
280
302
  수집·전송하는 것이 없습니다. 텔레메트리, 사용 통계, 오류 보고 전부 없습니다.
281
303
  대화 기록·되돌리기 이력·설정은 작업 폴더의 `.deel/` 안에만 남습니다.
282
304
 
283
- > 검증: `npm test` 의 network·web·mcp 검사 123항목. 허용되지 않은 서버에 실제로
305
+ > 검증: `npm test` 의 network·web·mcp 검사 159항목. 허용되지 않은 서버에 실제로
284
306
  > 요청이 **한 건도 닿지 않는지**, `--offline` 일 때 MCP 서버가 **한 번도 안
285
307
  > 뜨는지**까지 진짜 서버를 띄워서 확인합니다.
286
308
 
287
309
  ---
288
310
 
311
+ ## 바깥 API 붙이기
312
+
313
+ 로컬 모델이 이 도구의 기본값이고, 그건 안 바뀝니다. 다만 「사내에 GPU 가 없다」
314
+ 「이 한 가지만 큰 모델로 하고 싶다」 는 자리가 있어서, 벤더 API 도 붙을 수
315
+ 있게 열었습니다. **위의 모드가 그 문을 지킵니다.**
316
+
317
+ ```bash
318
+ deel setup
319
+ ```
320
+
321
+ 주소를 묻는 대신 **어디에 붙을지**를 묻습니다.
322
+
323
+ ```
324
+ 1. 열쇠만 있습니다 — 어디 것인지 찾아 드립니다 빈칸 1개
325
+ 2. 주소를 직접 넣기 (사내 게이트웨이 · 로컬) 빈칸 2개
326
+ 3. OpenAI (GPT) 빈칸 1개
327
+ 4. Anthropic (Claude) 빈칸 1개
328
+ 5. Google (Gemini) 빈칸 1개
329
+ 6. AWS Bedrock 빈칸 2개
330
+ ```
331
+
332
+ 1번이 핵심입니다. 열쇠 앞머리로 어디 것인지 짚어서 **한 곳만** 묻습니다.
333
+
334
+ ```
335
+ ❯ sk-ant-api03-••••
336
+ ✓ Anthropic (Claude) 열쇠로 보입니다. (열쇠가 sk-ant- 로 시작합니다)
337
+ 여기저기 던지지 않습니다.
338
+ ```
339
+
340
+ 벤더마다 찔러 보는 식으로 만들면 Anthropic 열쇠가 OpenAI 서버로, 다시 Google
341
+ 서버로 갑니다. 401 이 오고 끝이지만 **열쇠는 이미 갔습니다.** 그래서 모르는
342
+ 열쇠는 짐작하지 않고 사람에게 묻습니다.
343
+
344
+ Bedrock 은 리전을 고릅니다 — 서울(`ap-northeast-2`) 포함 다섯 곳과 「직접 입력」.
345
+ Claude 는 몸통 규격이 달라서 여섯 자리를 따로 흡수했습니다
346
+ ([1.7.0 릴리스 노트](docs/ko/releases/1.7.md#170)).
347
+
348
+ ### 바깥에 붙으면 파일 속 비밀도 가립니다
349
+
350
+ 로컬만 쓸 때는 파일에서 읽어 온 글을 **일부러 안 가렸습니다** — 가리면 모델이
351
+ 그 가림표를 다시 파일에 써서 사람의 진짜 열쇠를 지워 버리기 때문입니다.
352
+
353
+ 바깥으로 나가면 저울이 뒤집힙니다. `Read` 한 번이면 `.env` 가 통째로 남의
354
+ 서버 로그에 남고, 그건 되돌릴 수가 없습니다. 잃는 쪽은 다른 자리에서 막았습니다 —
355
+ `Write`·`Append`·`Edit` 이 가린 표를 파일에 못 씁니다.
356
+
357
+ ### 얼마 나갔는지 보입니다
358
+
359
+ ```
360
+ ❯ ─ 12.4초 · 도구 3회 · ↑8.2k ↓1.1k · $0.0271
361
+ ```
362
+
363
+ **값이 박힌 요금표가 없습니다.** 요금은 회사가 아무 때나 바꾸는 값이라, 소스에
364
+ 박아 두면 반년 뒤 이 도구는 틀린 금액을 자신 있게 찍는 도구가 됩니다.
365
+ `.deel/config.json` 에 적으면 셈합니다 — 100만 토큰당 달러입니다.
366
+
367
+ ```json
368
+ "요금": { "claude-opus-4-6": { "입력": 0, "출력": 0, "기준": "2026-09-01" } }
369
+ ```
370
+
371
+ 금액 옆에 **어디서 온 값인지·언제 기준인지**가 같이 뜨고, 반년이 지나면
372
+ `· 오래됨` 이 붙습니다. 모르면 안 찍습니다 — 로컬로만 쓰는 화면에는 돈 이야기가
373
+ 아예 안 뜹니다.
374
+
375
+ ---
376
+
289
377
  ## 로컬 모델 여러 개 쓰기
290
378
 
291
379
  로컬 런타임은 보통 하나만 쓰지 않습니다. Ollama 로 작은 모델을 돌리면서
@@ -924,7 +1012,7 @@ deel sbom --only sbom # SBOM 한 장만
924
1012
  ## 개발
925
1013
 
926
1014
  ```bash
927
- npm test 전체 검증 (4,932항목)
1015
+ npm test 전체 검증 (5,685항목)
928
1016
  npm run coverage 검사가 소스의 어디를 밟았는지
929
1017
  npm run verify 반입·통신 검증만
930
1018
  npm run bench 편집 성공률 측정
@@ -989,25 +1077,26 @@ zip 은 진짜 `unzip` 으로, tar 는 진짜 `tar` 가 만든 것을 읽혀 교
989
1077
 
990
1078
  | 판 | 무엇이 바뀌었나 |
991
1079
  |---|---|
992
- | **[1.6.3](docs/ko/releases.md#163)** | 일이 되고 있는데 헛돈다고 끊던 자리배열로 옮기면 무엇이 움직였는지가 사라졌다 |
993
- | **[1.6.2](docs/ko/releases.md#162)** | 누르면 멈추고, 시킨 대로 하고, 끊긴다 ESC · 되묻기 · 요청 누락 · 붙여넣기 접기 · 끊긴 자리 잇기 |
994
- | **[1.6.1](docs/ko/releases.md#161)** | 헛도는 턴을 만들던 자리들 울타리가 `/dev/null` 까지 막던 · 문서를 읽던 · 파일에서 그림이 사라지던 |
995
- | **[1.6.0](docs/ko/releases.md#160)** | 사내망에서 되던 것들프록시 · 429 · 윈도우 · 5만 저장소 · PDF · 캡처 붙여넣기 · 에디터 이어하기 |
996
- | **[1.5.8](docs/ko/releases.md#158)** | 5MB 문서를 919줄 8줄만 보던 · 정규식을 경로로 읽어 명령을 막던 |
997
- | **[1.5.7](docs/ko/releases.md#157)** | 한글 폴더에서 파일이 「범위 밖」이던 것 · 붙여넣기 · ESC |
998
- | **[1.5.6](docs/ko/releases.md#156)** | 막히면 물어본다 글로 묻고 턴을 끝내는 대신에 |
999
- | **[1.5.5](docs/ko/releases.md#155)** | 계획을 세우면 방이 찬다 「한 명뿐」은 고정이 아니라 버그였다 |
1000
- | [1.5.4](docs/ko/releases.md#154) | 방에 하루가 흐른다아침·낮·노을·밤 · 벽시계 · 식은 커피 |
1001
- | [1.5.3](docs/ko/releases.md#153) | 맥에서 걸린 가지 줄바꿈 안내 · 사무실이 안 사라짐 · `/motion` 하나로 |
1002
- | [1.5.2](docs/ko/releases.md#152) | 적대적 리뷰가 남긴 나머지를 전부 정리했다 화면이 거짓말하던 자리들 |
1003
- | [1.5.1](docs/ko/releases.md#151) | 1.5.0 넣은 개가 망가진 나갔다. 그것을 고친다 |
1004
- | [1.5.0](docs/ko/releases.md#150) | 줄바꿈이 생겼고, 화면이 재미있어졌고, 그러면서 오히려 가벼워졌다 |
1005
- | [1.4.3](docs/ko/releases.md#143) | README 다른지 말하고, 심사서의 빠진 한 줄을 채운다 |
1006
- | [1.4.2](docs/ko/releases.md#142) | 1.4.1 보안 수정 전에 나갔다 그걸 바로잡는 |
1007
- | [1.4.1](docs/ko/releases.md#141) | 기능 없이, 실제로 찾은 것만 고친다 윈도우 abort·ReDoS·XSS |
1008
- | [1.4.0](docs/ko/releases.md#140) | deel 얼굴을 갖고, 영어로도 말하고, 뜻까지 본다 열한 자리 |
1009
- | [1.3.0](docs/ko/releases.md#130) | 대신 증거, 터미널 대신 에디터여섯 자리 |
1010
- | [1.2.0](docs/ko/releases.md#120) | 대화가 끊기지 않게 — 여섯 자리 |
1080
+ | **[1.7.0](docs/ko/releases/1.7.md#170)** | 로컬은 그대로 두고, 말했을 때만 바깥으로모드 · 벤더 붙이기 · 자동 마스킹 · 돈 표시 |
1081
+ | [1.6.3](docs/ko/releases/1.6.md#163) | 일이 되고 있는데 헛돈다고 끊던 자리배열로 옮기면 무엇이 움직였는지가 사라졌다 |
1082
+ | **[1.6.2](docs/ko/releases/1.6.md#162)** | 누르면 멈추고, 시킨 대로 하고, 끊긴다 ESC · 되묻기 · 요청 누락 · 붙여넣기 접기 · 끊긴 자리 잇기 |
1083
+ | **[1.6.1](docs/ko/releases/1.6.md#161)** | 헛도는 턴을 만들던 자리들울타리가 `/dev/null` 까지 막던 · 문서를 읽던 · 파일에서 그림이 사라지던 |
1084
+ | **[1.6.0](docs/ko/releases/1.6.md#160)** | 사내망에서 되던 것들 프록시 · 429 · 윈도우 · 5만 저장소 · PDF · 캡처 붙여넣기 · 에디터 이어하기 |
1085
+ | **[1.5.8](docs/ko/releases/1.5.md#158)** | 5MB 문서를 919줄 8줄만 보던 것 · 정규식을 경로로 읽어 명령을 막던 것 |
1086
+ | **[1.5.7](docs/ko/releases/1.5.md#157)** | 한글 폴더에서 파일이 「범위 밖」이던 · 붙여넣기 · ESC |
1087
+ | **[1.5.6](docs/ko/releases/1.5.md#156)** | 막히면 물어본다글로 묻고 턴을 끝내는 대신에 |
1088
+ | **[1.5.5](docs/ko/releases/1.5.md#155)** | 계획을 세우면 방이 찬다 「한 명뿐」은 고정이 아니라 버그였다 |
1089
+ | [1.5.4](docs/ko/releases/1.5.md#154) | 방에 하루가 흐른다아침·낮·노을·밤 · 벽시계 · 식은 커피 |
1090
+ | [1.5.3](docs/ko/releases/1.5.md#153) | 맥에서 걸린 가지 줄바꿈 안내 · 사무실이 사라짐 · `/motion` 하나로 |
1091
+ | [1.5.2](docs/ko/releases/1.5.md#152) | 적대적 리뷰가 남긴 나머지를 전부 정리했다 화면이 거짓말하던 자리들 |
1092
+ | [1.5.1](docs/ko/releases/1.5.md#151) | 1.5.0 넣은 개가 망가진 채 나갔다. 그것을 고친다 |
1093
+ | [1.5.0](docs/ko/releases/1.5.md#150) | 줄바꿈이 생겼고, 화면이 재미있어졌고, 그러면서 오히려 가벼워졌다 |
1094
+ | [1.4.3](docs/ko/releases/1.4.md#143) | README 다른지 말하고, 심사서의 빠진 줄을 채운다 |
1095
+ | [1.4.2](docs/ko/releases/1.4.md#142) | 1.4.1 보안 수정 전에 나갔다그걸 바로잡는 |
1096
+ | [1.4.1](docs/ko/releases/1.4.md#141) | 기능 없이, 실제로 찾은 것만 고친다윈도우 abort·ReDoS·XSS |
1097
+ | [1.4.0](docs/ko/releases/1.4.md#140) | deel 얼굴을 갖고, 영어로도 말하고, 뜻까지 본다 열한 자리 |
1098
+ | [1.3.0](docs/ko/releases/1.3.md#130) | 대신 증거, 터미널 대신 에디터 — 여섯 자리 |
1099
+ | [1.2.0](docs/ko/releases/1.2.md#120) | 대화가 끊기지 않게 — 여섯 자리 |
1011
1100
 
1012
1101
  무엇이 왜 바뀌었는지는 **[릴리스 노트](docs/ko/releases.md)** 에 있습니다.
1013
1102
 
package/bin/deel.js CHANGED
@@ -106,7 +106,7 @@ function runSbom(flags) {
106
106
  // 실제로 이랬다 — deel run --json "검사 돌려줘" 를 쳤더니 --json 이 뒤의 말을
107
107
  // 통째로 삼켰다. 시킬 말이 사라졌으니 "무엇을 시킬지 적어 주세요" 가 떴는데,
108
108
  // 화면만 보면 왜 그런지 알 길이 없다. 깃발을 앞에 두는 것은 아주 흔한 습관이다.
109
- const BOOL = new Set(['help', 'version', 'offline', 'continue', 'json', 'quiet', 'yes', 'no-tui', 'tui']);
109
+ const BOOL = new Set(['help', 'version', 'offline', 'online', 'continue', 'json', 'quiet', 'yes', 'no-tui', 'tui']);
110
110
 
111
111
  function parse(argv) {
112
112
  const flags = {};
@@ -175,7 +175,11 @@ function help() {
175
175
  say(` ${c.gray('--think <수준>')} off / low / medium(기본) / high / max`);
176
176
  say(` ${c.gray('--effort <배분>')} even(균일) / save(절약, 기본) / deep(깊게)`);
177
177
  say(` ${c.gray('--no-tui')} 입력 상자 없이 줄 화면으로 (파이프·기록·좁은 터미널)`);
178
- say(` ${c.gray('--offline')} 이 컴퓨터 밖으로는 아무것도 보냄 (자물쇠)`);
178
+ // 실행 모드 셋. 기본이 잠겨 있다는 것을 여기서 분명히 말한다 —
179
+ // 「--online 이 있다」 보다 「기본은 안 나간다」 가 사람이 알아야 할 쪽이다.
180
+ say(` ${c.gray('(기본)')} ⌂ 이 안 — 바깥 주소면 한 번 물어보고 기억합니다`);
181
+ say(` ${c.gray('--online')} ↗ 바깥 — 묻지 않고 나갑니다 ${c.gray('(스크립트·CI 처럼 물어볼 사람이 없을 때)')}`);
182
+ say(` ${c.gray('--offline')} ⛊ 봉인 — 기억해 둔 허가까지 무시하고 막습니다 ${c.gray('(사내망은 그대로 갑니다)')}`);
179
183
  say(` ${c.gray('--continue')} 이 폴더에서 가장 최근 대화 이어하기`);
180
184
  say(` ${c.gray('--resume <id>')} 골라서 이어하기 (deel sessions 로 id 확인)`);
181
185
  say('');
@@ -210,7 +214,18 @@ async function main() {
210
214
  process.exit(1);
211
215
  }
212
216
 
213
- const { cmd, args, flags } = parse(process.argv.slice(2));
217
+ const { cmd: 친명령, args, flags } = parse(process.argv.slice(2));
218
+
219
+ /*
220
+ * `deel online` · `deel offline` 은 깃발의 별칭이다.
221
+ *
222
+ * 사람은 이것을 「모드로 켠다」 고 생각한다 — `deel --online` 보다
223
+ * `deel online` 이 먼저 손에서 나온다. 둘 다 받는다. 안 받으면 "모르는
224
+ * 명령입니다" 가 뜨는데, 그 화면에서는 무엇을 잘못 쳤는지 알 길이 없다.
225
+ */
226
+ const cmd = (친명령 === 'online' || 친명령 === 'offline')
227
+ ? (flags[친명령] = true, '')
228
+ : 친명령;
214
229
 
215
230
  /*
216
231
  * 판 번호.
@@ -241,6 +256,7 @@ async function main() {
241
256
  think: flags.think ? String(flags.think) : undefined,
242
257
  effort: flags.effort ? String(flags.effort) : undefined,
243
258
  offline: flags.offline === true || flags.offline === 'true',
259
+ online: flags.online === true || flags.online === 'true',
244
260
  yes: flags.yes === true || flags.yes === 'true',
245
261
  json: flags.json === true || flags.json === 'true',
246
262
  quiet: flags.quiet === true || flags.quiet === 'true',
@@ -261,6 +277,7 @@ async function main() {
261
277
  // --tui 터미널이면 무조건 입력 상자를 켠다
262
278
  tui: flags['no-tui'] === true ? false : (flags.tui === true ? true : null),
263
279
  offline: flags.offline === true || flags.offline === 'true',
280
+ online: flags.online === true || flags.online === 'true',
264
281
  continue: flags.continue === true || flags.c === true,
265
282
  sessionId: typeof flags.resume === 'string' ? flags.resume : (flags.resume === true ? null : undefined),
266
283
  });
@@ -281,6 +298,7 @@ async function main() {
281
298
  think: flags.think ? String(flags.think) : undefined,
282
299
  effort: flags.effort ? String(flags.effort) : undefined,
283
300
  offline: flags.offline === true || flags.offline === 'true',
301
+ online: flags.online === true || flags.online === 'true',
284
302
  });
285
303
  case 'status':
286
304
  return showStatus();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deel-local-cli",
3
- "version": "1.6.3",
3
+ "version": "1.7.0",
4
4
  "description": "로컬 모델·사내 게이트웨이 전용 코딩 에이전트 CLI — 외부 의존성 0개 / Zero-dependency coding agent CLI for local LLMs and private gateways",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -51,7 +51,7 @@
51
51
  "verify": "node test/no-bundle.test.js && node test/network.test.js && node test/web.test.js",
52
52
  "bench": "node test/edit-bench.js",
53
53
  "demo": "node test/demo.js",
54
- "check": "node --check bin/deel.js && node --check src/repl.js && node --check src/oneshot.js && node --check src/commands.js && node --check src/agent/loop.js && node --check src/agent/session.js && node --check src/agent/effort.js && node --check src/agent/modes.js && node --check src/agent/route.js && node --check src/agent/askcheck.js && node --check src/agent/asks.js && node --check src/agent/models.js && node --check src/agent/grade.js && node --check src/agent/mention.js && node --check src/agent/project.js && node --check src/tools/encoding.js && node --check src/tools/excel-com.js && node --check src/tools/excel.js && node --check src/tools/xlsx.js && node --check src/tools/docs.js && node --check src/tools/convert.js && node --check src/tools/pdf.js && node --check src/tools/clipboard.js && node --check src/agent/compact.js && node --check src/agent/store.js && node --check src/agent/sessionui.js && node --check src/backend/adapter.js && node --check src/backend/ctxsize.js && node --check src/backend/probe.js && node --check src/backend/detect.js && node --check src/backend/http.js && node --check src/backend/retry.js && node --check src/backend/proxy.js && node --check src/backend/azure.js && node --check src/backend/vision.js && node --check src/backend/quota.js && node --check src/backend/scan.js && node --check src/backend/scanui.js && node --check src/tools/index.js && node --check src/tools/desc.en.js && node --check src/tools/lsp.js && node --check src/lsp/rpc.js && node --check src/lsp/servers.js && node --check src/lsp/client.js && node --check src/lsp/diag.js && node --check src/tools/fsutil.js && node --check src/tools/ignore.js && node --check src/tools/spawn.js && node --check src/tools/fastgrep.js && node --check src/tools/edit-match.js && node --check src/tools/webfetch.js && node --check src/tools/todo.js && node --check src/tools/jobs.js && node --check src/tools/shell.js && node --check src/skills/discover.js && node --check src/plugins/manage.js && node --check src/pack/zip.js && node --check src/pack/tar.js && node --check src/pack/selfpack.js && node --check src/safety/guard.js && node --check src/safety/undo.js && node --check src/safety/audit.js && node --check src/safety/keystore.js && node --check src/safety/policy.js && node --check src/safety/network.js && node --check src/setup.js && node --check src/report.js && node --check src/config.js && node --check src/completion.js && node --check src/ui/diff.js && node --check src/ui/ansi.js && node --check src/ui/status.js && node --check src/ui/level.js && node --check src/ui/prompt.js && node --check src/ui/spinner.js && node --check src/ui/motion.js && node --check src/ui/office.js && node --check src/ui/notify.js && node --check src/ui/intro.js && node --check src/ui/banner.js && node --check src/ui/export.js && node --check src/i18n/index.js && node --check src/i18n/ko.js && node --check src/i18n/en.js && node --check src/i18n/ja.js && node --check src/i18n/zh.js && node --check src/preview/serve.js && node --check src/ui/working.js && node --check src/ui/inputbox.js && node --check src/ui/wrap.js && node --check src/ui/pastechip.js && node --check src/ui/md.js && node --check src/agent/threads.js && node --check src/agent/evolve.js && node --check src/agent/pins.js && node --check src/agent/card.js && node --check src/agent/preset.js && node --check src/agent/evidence.js && node --check src/agent/commit.js && node --check src/agent/review.js && node --check src/acp/jsonrpc.js && node --check src/acp/map.js && node --check src/acp/serve.js && node --check src/pack/sbom.js && node --check src/safety/secrets.js && echo OK",
54
+ "check": "node --check bin/deel.js && node --check src/repl.js && node --check src/oneshot.js && node --check src/commands.js && node --check src/agent/loop.js && node --check src/agent/session.js && node --check src/agent/effort.js && node --check src/agent/modes.js && node --check src/agent/route.js && node --check src/agent/askcheck.js && node --check src/agent/asks.js && node --check src/agent/models.js && node --check src/agent/grade.js && node --check src/agent/mention.js && node --check src/agent/project.js && node --check src/tools/encoding.js && node --check src/tools/excel-com.js && node --check src/tools/excel.js && node --check src/tools/xlsx.js && node --check src/tools/docs.js && node --check src/tools/convert.js && node --check src/tools/pdf.js && node --check src/tools/clipboard.js && node --check src/agent/compact.js && node --check src/agent/store.js && node --check src/agent/sessionui.js && node --check src/backend/adapter.js && node --check src/backend/ctxsize.js && node --check src/backend/probe.js && node --check src/backend/detect.js && node --check src/backend/http.js && node --check src/backend/retry.js && node --check src/backend/proxy.js && node --check src/backend/azure.js && node --check src/backend/vision.js && node --check src/backend/quota.js && node --check src/backend/price.js && node --check src/backend/scan.js && node --check src/backend/scanui.js && node --check src/tools/index.js && node --check src/tools/desc.en.js && node --check src/tools/lsp.js && node --check src/lsp/rpc.js && node --check src/lsp/servers.js && node --check src/lsp/client.js && node --check src/lsp/diag.js && node --check src/tools/fsutil.js && node --check src/tools/ignore.js && node --check src/tools/spawn.js && node --check src/tools/fastgrep.js && node --check src/tools/edit-match.js && node --check src/tools/webfetch.js && node --check src/tools/todo.js && node --check src/tools/jobs.js && node --check src/tools/shell.js && node --check src/skills/discover.js && node --check src/plugins/manage.js && node --check src/pack/zip.js && node --check src/pack/tar.js && node --check src/pack/selfpack.js && node --check src/safety/guard.js && node --check src/safety/undo.js && node --check src/safety/audit.js && node --check src/safety/keystore.js && node --check src/safety/policy.js && node --check src/safety/network.js && node --check src/safety/runmode.js && node --check src/providers/index.js && node --check src/providers/openai.js && node --check src/providers/anthropic.js && node --check src/providers/gemini.js && node --check src/providers/bedrock.js && node --check src/providers/custom.js && node --check src/setup.js && node --check src/report.js && node --check src/config.js && node --check src/completion.js && node --check src/ui/diff.js && node --check src/ui/ansi.js && node --check src/ui/status.js && node --check src/ui/level.js && node --check src/ui/prompt.js && node --check src/ui/spinner.js && node --check src/ui/motion.js && node --check src/ui/office.js && node --check src/ui/notify.js && node --check src/ui/intro.js && node --check src/ui/banner.js && node --check src/ui/export.js && node --check src/i18n/index.js && node --check src/i18n/ko.js && node --check src/i18n/en.js && node --check src/i18n/ja.js && node --check src/i18n/zh.js && node --check src/preview/serve.js && node --check src/ui/working.js && node --check src/ui/inputbox.js && node --check src/ui/wrap.js && node --check src/ui/pastechip.js && node --check src/ui/histline.js && node --check src/ui/md.js && node --check src/agent/threads.js && node --check src/agent/evolve.js && node --check src/agent/pins.js && node --check src/agent/card.js && node --check src/agent/preset.js && node --check src/agent/evidence.js && node --check src/agent/commit.js && node --check src/agent/review.js && node --check src/acp/jsonrpc.js && node --check src/acp/map.js && node --check src/acp/serve.js && node --check src/pack/sbom.js && node --check src/safety/secrets.js && echo OK",
55
55
  "coverage": "node test/coverage.mjs",
56
56
  "prepublishOnly": "npm run check && npm test"
57
57
  },
package/src/acp/serve.js CHANGED
@@ -42,6 +42,7 @@ import { 말 as 옮긴말 } from '../i18n/index.js';
42
42
  import { 알림채움 } from '../backend/retry.js';
43
43
  import { discover } from '../skills/discover.js';
44
44
  import { allowEndpoint, setOffline } from '../safety/network.js';
45
+ import { 지금모드, 바깥인가, 나갈수있나 } from '../safety/runmode.js';
45
46
  import { 주소가리기 } from '../safety/secrets.js';
46
47
  import { probeCtx, 기본값 as CTX_DEFAULT } from '../backend/ctxsize.js';
47
48
  import { 다붙이기 } from '../backend/mcp.js';
@@ -138,9 +139,28 @@ export async function acp(opts = {}) {
138
139
  streaming: prof.streaming ?? false,
139
140
  tools: prof.tools ?? false, json: prof.json ?? false, think: prof.think ?? false,
140
141
  };
142
+ /*
143
+ * 바깥으로 나가는 연결은 허가가 있어야 연다 (safety/runmode.js).
144
+ *
145
+ * 에디터에는 승인 창이 있지만 그건 **도구 실행**을 묻는 창이고, 「이 대화가
146
+ * 통째로 바깥으로 나갑니다」 를 물을 자리는 규격에 없다. 그래서 여기서는
147
+ * 묻지 않고 또렷하게 거절한다 — 에디터 화면에 이 글이 그대로 뜬다.
148
+ */
149
+ const 바깥연결 = 바깥인가(conn.base);
150
+ const 실행모드 = 지금모드({
151
+ online: opts.online === true,
152
+ // 관리 정책이 offline 을 못박아 뒀으면 옵션과 상관없이 켠다 (safety/policy.js).
153
+ offline: !!(opts.offline ?? prof.offline ?? cfg?.offline),
154
+ });
155
+ const 나감 = 나갈수있나(실행모드, { 바깥: 바깥연결, 허가: prof.online === true });
156
+ if (나감.물어볼까) {
157
+ const 어디 = (() => { try { return new URL(conn.base).host; } catch { return conn.base; } })();
158
+ throw 잘못된인자오류(
159
+ `이 연결은 이 컴퓨터 밖으로 나갑니다 (${주소가리기(어디)}).`
160
+ + ' 터미널에서 deel 을 한 번 켜서 허락하거나, deel acp --online 으로 띄우세요.');
161
+ }
141
162
  allowEndpoint(conn.base);
142
- // 관리 정책이 offline 을 못박아 뒀으면 옵션과 상관없이 켠다 (safety/policy.js).
143
- if (opts.offline ?? prof.offline ?? cfg?.offline) setOffline(true);
163
+ if (실행모드.허가무시) setOffline(true);
144
164
 
145
165
  const session = new Session(conn, {
146
166
  root,
@@ -151,6 +171,9 @@ export async function acp(opts = {}) {
151
171
  think: opts.think ?? 'medium',
152
172
  effort: opts.effort ?? 'save',
153
173
  });
174
+ // 지금 어느 실행 모드인가. 화면이 첫 줄에 이걸 그린다(ui/status.js).
175
+ // session 에 실어 두는 까닭은, 대화 도중 /model 로 옮겨도 같은 자리를 보게 하려는 것이다.
176
+ session.실행모드 = 실행모드;
154
177
 
155
178
  const found = discover(root);
156
179
  session.skills = found.skills;