deel-local-cli 1.2.0 → 1.4.1
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 +301 -1537
- package/README.md +272 -1582
- package/bin/deel.js +73 -4
- package/package.json +8 -3
- package/src/acp/jsonrpc.js +230 -0
- package/src/acp/map.js +219 -0
- package/src/acp/serve.js +556 -0
- package/src/agent/card.js +129 -0
- package/src/agent/compact.js +10 -2
- package/src/agent/effort.js +5 -0
- package/src/agent/evidence.js +186 -0
- package/src/agent/grade.js +20 -0
- package/src/agent/loop.js +134 -13
- package/src/agent/models.js +169 -0
- package/src/agent/modes.js +47 -1
- package/src/agent/pins.js +140 -0
- package/src/agent/preset.js +113 -0
- package/src/agent/project.js +10 -4
- package/src/agent/session.js +233 -13
- package/src/agent/store.js +31 -0
- package/src/backend/adapter.js +14 -0
- package/src/commands.js +616 -52
- package/src/i18n/en.js +265 -0
- package/src/i18n/index.js +126 -0
- package/src/i18n/ko.js +252 -0
- package/src/lsp/client.js +459 -0
- package/src/lsp/diag.js +112 -0
- package/src/lsp/rpc.js +84 -0
- package/src/lsp/servers.js +218 -0
- package/src/oneshot.js +19 -0
- package/src/pack/sbom.js +218 -0
- package/src/pack/selfpack.js +19 -3
- package/src/preview/serve.js +19 -2
- package/src/repl.js +193 -8
- package/src/safety/secrets.js +205 -0
- package/src/safety/undo.js +10 -3
- package/src/tools/desc.en.js +221 -0
- package/src/tools/docs.js +252 -0
- package/src/tools/index.js +190 -6
- package/src/tools/lsp.js +327 -0
- package/src/tools/task.js +30 -2
- package/src/ui/ansi.js +45 -0
- package/src/ui/approve.js +25 -21
- package/src/ui/banner.js +245 -0
- package/src/ui/export.js +217 -0
- package/src/ui/inputbox.js +37 -7
- package/src/ui/intro.js +206 -0
- package/src/ui/level.js +11 -5
- package/src/ui/notify.js +101 -0
- package/src/ui/status.js +181 -35
package/README.en.md
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/hero-en-dark.svg">
|
|
5
|
+
<img alt="deel — stays on this machine" src="docs/assets/hero-en-light.svg" width="620">
|
|
6
|
+
</picture>
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
### A coding-agent CLI that runs on local models and private gateways only
|
|
6
9
|
|
|
7
10
|
Zero dependencies · Node 20+ · Exactly one place your source can go
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
<br>
|
|
13
|
+
|
|
14
|
+
[](https://www.npmjs.com/package/deel-local-cli)
|
|
15
|
+
[](https://www.npmjs.com/package/deel-local-cli)
|
|
16
|
+
[](https://nodejs.org)
|
|
17
|
+
[](LICENSE)
|
|
18
|
+
|
|
19
|
+
[](https://github.com/jysvai/deel-local-cli/actions/workflows/test.yml)
|
|
20
|
+
[](https://github.com/jysvai/deel-local-cli/actions/workflows/codeql.yml)
|
|
21
|
+
[](docs/en/develop.md)
|
|
22
|
+
|
|
23
|
+
[](https://www.npmjs.com/package/deel-local-cli?activeTab=dependencies)
|
|
24
|
+
[](package.json)
|
|
25
|
+
[](#where-your-data-can-go)
|
|
26
|
+
[](#where-your-data-can-go)
|
|
27
|
+
|
|
28
|
+
**[한국어](README.md)** · [Corporate review](#corporate-review-package) · [Troubleshooting](#troubleshooting) · [Full docs](docs/en/)
|
|
10
29
|
|
|
11
30
|
</div>
|
|
12
31
|
|
|
@@ -20,12 +39,12 @@ Zero dependencies · Node 20+ · Exactly one place your source can go
|
|
|
20
39
|
│ Sends to this machine 127.0.0.1:11434 ← nowhere else │
|
|
21
40
|
│ Link streaming · tools · reasoning control │
|
|
22
41
|
│ Folder C:\work\myproject │
|
|
23
|
-
│ Approval ⏵⏵
|
|
42
|
+
│ Approval ⏵⏵ auto-approve — nothing is asked; /undo is the net│
|
|
24
43
|
│ Shift+Tab to change · Tab completes a / command │
|
|
25
44
|
│ This PC 337 skills · 127 commands · 42 plugins │
|
|
26
45
|
╰──────────────────────────────────────────────────────────────╯
|
|
27
46
|
|
|
28
|
-
▏myproject · qwen2.5-coder:7b ▏ ▰▰▱▱▱▱▱▱▱▱ 22% 28k/128k ▏ ◎
|
|
47
|
+
▏myproject · qwen2.5-coder:7b ▏ ▰▰▱▱▱▱▱▱▱▱ 22% 28k/128k ▏ ◎ Auto · ◇ medium·save · ⏵⏵ auto
|
|
29
48
|
❯ unify the logging style
|
|
30
49
|
|
|
31
50
|
❊ Grep(console.log)
|
|
@@ -59,6 +78,8 @@ Zero dependencies · Node 20+ · Exactly one place your source can go
|
|
|
59
78
|
- [Auto-compaction](#auto-compaction)
|
|
60
79
|
- [Resuming a conversation](#resuming-a-conversation)
|
|
61
80
|
- [Attaching tools from outside (MCP)](#attaching-tools-from-outside-mcp)
|
|
81
|
+
- [Inside your editor (ACP)](#inside-your-editor-acp)
|
|
82
|
+
- [Keeping secrets out of the conversation](#keeping-secrets-out-of-the-conversation)
|
|
62
83
|
- [Safety](#safety)
|
|
63
84
|
- [Corporate review package](#corporate-review-package)
|
|
64
85
|
- [Configuration](#configuration)
|
|
@@ -66,7 +87,19 @@ Zero dependencies · Node 20+ · Exactly one place your source can go
|
|
|
66
87
|
- [Development](#development)
|
|
67
88
|
- [Release notes](#release-notes)
|
|
68
89
|
|
|
69
|
-
|
|
90
|
+
This page is the **summary**. Each section links to the detail behind it.
|
|
91
|
+
|
|
92
|
+
| Full docs | What is in there |
|
|
93
|
+
|---|---|
|
|
94
|
+
| [Models](docs/en/models.md) | Grade and window size · Korean-model presets · project detection |
|
|
95
|
+
| [The screen](docs/en/interface.md) | The input box · work modes · simple vs developer · what it asks about |
|
|
96
|
+
| [Tools in depth](docs/en/tools.md) | `Outline` · `Verify` · `Task` · `Jobs` · `Append` · `Def`/`Refs` · edit matching |
|
|
97
|
+
| [Korean documents and Excel](docs/en/documents.md) | hwpx/docx/pptx · encoding · Excel → CSV |
|
|
98
|
+
| [Extending](docs/en/extend.md) | Skills · plugins · MCP · ACP |
|
|
99
|
+
| [Speed and spend](docs/en/tuning.md) | Per-stage effort · the prefix cache · context length |
|
|
100
|
+
| [Safety and corporate review](docs/en/safety.md) | Undo · working scope · audit log · the review package |
|
|
101
|
+
| [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.0](docs/en/releases.md#140) · [1.3.0](docs/en/releases.md#130) · [1.2.0](docs/en/releases.md#120) |
|
|
70
103
|
|
|
71
104
|
---
|
|
72
105
|
|
|
@@ -97,6 +130,29 @@ deel audit # full review sheet
|
|
|
97
130
|
|
|
98
131
|
## Quick start
|
|
99
132
|
|
|
133
|
+
### The screen speaks English too
|
|
134
|
+
|
|
135
|
+
deel is written in Korean — the code, the function names, the comments. That part stays.
|
|
136
|
+
What you see on screen does not have to.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
DEEL_LANG=en deel # this run only
|
|
140
|
+
/lang en # and remember it
|
|
141
|
+
/lang # how much is translated so far
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Untranslated lines come through in Korean rather than as blanks, and `/lang` tells you exactly
|
|
145
|
+
how many are left.
|
|
146
|
+
|
|
147
|
+
What the model reads follows the same switch. Set it to English and the rules, the mode
|
|
148
|
+
instructions, and the tool descriptions all go out in English — so the model answers you in
|
|
149
|
+
English instead of Korean. That side is cheaper, too: the part of the window that ships on every
|
|
150
|
+
single request drops from about 4,900 tokens to about 3,450 — on a 32k model, from 15% of the
|
|
151
|
+
window to 10.5%.
|
|
152
|
+
|
|
153
|
+
Tool names and argument names stay Korean (`목적`, `할일`, `번호`). Those are identifiers, not
|
|
154
|
+
prose — rename them and the tool stops being called at all.
|
|
155
|
+
|
|
100
156
|
### Install
|
|
101
157
|
|
|
102
158
|
```bash
|
|
@@ -207,140 +263,9 @@ $ deel scan
|
|
|
207
263
|
|
|
208
264
|
Switch with `/model` mid-conversation — **the conversation carries over.**
|
|
209
265
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
### It adapts to whatever model is attached
|
|
214
|
-
|
|
215
|
-
If you move between models, any number tuned for one of them is wrong for all the others.
|
|
216
|
-
So **no number is hardcoded.**
|
|
217
|
-
|
|
218
|
-
There are two axes. They are easy to confuse, so they have separate commands.
|
|
219
|
-
|
|
220
|
-
| | What it measures | Command |
|
|
221
|
-
|---|---|---|
|
|
222
|
-
| **Window size** | how much it can hold | `/ctx` |
|
|
223
|
-
| **Model grade** | how much it can do on its own | `/grade` |
|
|
224
|
-
|
|
225
|
-
They do not move together. A 3B model with a 128k window exists; so does a very good model
|
|
226
|
-
with 32k. Treat them as one axis and you hold one back while overrunning the other.
|
|
227
|
-
|
|
228
|
-
**Derived from window size** (`src/agent/budget.js`):
|
|
229
|
-
|
|
230
|
-
| | 8k | 32k | 131k | 655k |
|
|
231
|
-
|---|---|---|---|---|
|
|
232
|
-
| Steps per turn (code) | 16 | 48 | 192 | 200 |
|
|
233
|
-
| `Read` lines | 200 | 384 | 1,536 | 4,000 |
|
|
234
|
-
| `Glob` results | 50 | 192 | 768 | 1,000 |
|
|
235
|
-
| `Outline` lines | 120 | 480 | 1,920 | 2,500 |
|
|
236
|
-
| `WebFetch` chars | 4,000 | 12,800 | 51,200 | 120,000 |
|
|
237
|
-
| Subtask summary | 400 | 1,600 | 4,000 | 4,000 |
|
|
238
|
-
|
|
239
|
-
**Derived from model grade** (`src/agent/grade.js`):
|
|
240
|
-
|
|
241
|
-
| | small | medium | large |
|
|
242
|
-
|---|---|---|---|
|
|
243
|
-
| Files per `Write` | 3 | 6 | 12 |
|
|
244
|
-
| Split-writing threshold | 200 lines | 400 lines | 800 lines |
|
|
245
|
-
| Spell out the procedure | yes | yes | **no — give the goal** |
|
|
246
|
-
| Require verification | yes | yes | **yes** (grade-independent) |
|
|
247
|
-
|
|
248
|
-
The grade is decided like this:
|
|
249
|
-
|
|
250
|
-
1. **First guess from the name.** `qwen2.5-coder-7b` -> small, `llama-3.3-70b` -> large.
|
|
251
|
-
Version numbers (`2.5`) and quantisation tags (`q4_k_m`) are not read as sizes.
|
|
252
|
-
A name that says nothing means **medium**, not small — a corporate gateway is exactly
|
|
253
|
-
that case, and the models behind one are usually big. Guessing small holds them back.
|
|
254
|
-
2. **Corrected by what actually happened.** Truncated tool arguments, empty answers,
|
|
255
|
-
failed edits and repeats are counted. A model labelled 70B that truncates every step is
|
|
256
|
-
dropped to **small**; a 7B that runs ten clean steps is raised one level. The name is a
|
|
257
|
-
guess; what happened is a fact.
|
|
258
|
-
3. **You win if you say so.** `/grade large`, and `/grade auto` hands it back.
|
|
259
|
-
|
|
260
|
-
The status line shows `◈ small?`. The question mark means **still a guess** — a guess is
|
|
261
|
-
not presented with the same face as something measured.
|
|
262
|
-
|
|
263
|
-
The grade only changes **how much hand-holding you get**. Working scope, approval mode,
|
|
264
|
-
undo and the audit log are identical at every grade. There is no "it is a good model, so
|
|
265
|
-
skip verification" — that is exactly how a good model's mistake goes unnoticed.
|
|
266
|
-
|
|
267
|
-
### Small windows get a smaller fixed share
|
|
268
|
-
|
|
269
|
-
The system prompt and the tool definitions go out **in full on every request**. Compaction
|
|
270
|
-
(`/compact`) cannot shrink them. Once that share passes half the window there is no room
|
|
271
|
-
left however well you fold, and it looks like "the model suddenly got stupid".
|
|
272
|
-
|
|
273
|
-
Adding three tools (`Outline`, `Verify`, `Task`) pushed it to **49%** at 8k. Dropping a
|
|
274
|
-
tool would have fixed it — and would have made small models capable of different things,
|
|
275
|
-
which is the thing to avoid. The descriptions were trimmed to the window instead.
|
|
276
|
-
|
|
277
|
-
| | 8k | 16k | 32k+ |
|
|
278
|
-
|---|---|---|---|
|
|
279
|
-
| Base rules | short form | short form | full |
|
|
280
|
-
| Mode description | short form | short form | full |
|
|
281
|
-
| Tool descriptions | 90 chars | 140 chars | 220 / full |
|
|
282
|
-
| Obvious param descriptions | dropped | kept | kept |
|
|
283
|
-
| Descriptions inside array items | dropped | dropped | kept |
|
|
284
|
-
| **Fixed share** | **2,712 tokens (33%)** | 3,290 (21%) | 4,745 (4% at 131k) |
|
|
285
|
-
|
|
286
|
-
The **folder brief** adds roughly 80 more tokens at 8k (below). That value varies by
|
|
287
|
-
folder, so it is not in the table.
|
|
288
|
-
|
|
289
|
-
**Tool names and arguments are untouched.** What is possible is identical in every window;
|
|
290
|
-
what disappears is only the argument for *why* to use a tool. Large windows keep it,
|
|
291
|
-
because that argument earns its keep — those two sentences are what make a model call
|
|
292
|
-
`Outline` before `Read`.
|
|
293
|
-
|
|
294
|
-
A test pins these numbers (`test/compact.test.js`).
|
|
295
|
-
|
|
296
|
-
### On startup it reads what kind of project this folder is
|
|
297
|
-
|
|
298
|
-
Started in a folder of someone else's code, the model began knowing nothing. So it
|
|
299
|
-
retraced the same three steps every time — scan the top level, read `package.json`, find
|
|
300
|
-
out how tests are run. **On a local model each step is 20-40 seconds, so two minutes go
|
|
301
|
-
by before the work even starts.**
|
|
302
|
-
|
|
303
|
-
The worse case is the model *skipping* those three steps. Then it creates files by its
|
|
304
|
-
own conventions without knowing what the project already uses — a `requirements.txt`
|
|
305
|
-
dropped into an npm project.
|
|
306
|
-
|
|
307
|
-
The answers are all knowable at startup, so they are read once and put in the prompt.
|
|
308
|
-
|
|
309
|
-
The brief itself is written in Korean, like everything else deel puts on screen — this is
|
|
310
|
-
deel's own folder, wrapped here for width:
|
|
311
|
-
|
|
312
|
-
```
|
|
313
|
-
--- 이 폴더 --- (this folder)
|
|
314
|
-
node 프로젝트 (deel-local-cli) · git main
|
|
315
|
-
돌릴 수 있는 것: npm start · npm test · npm run bench · npm run chat · npm run check ·
|
|
316
|
-
npm run coverage · npm run demo · npm run diagnose (runnable)
|
|
317
|
-
위쪽: bin/ src/ test/ LICENSE README.en.md README.md package.json report.txt (top level)
|
|
318
|
-
위쪽 한 겹만 본 것이다. 안을 알아야 하면 Outline 을 불러라.
|
|
319
|
-
(top level only — call Outline to see inside)
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
**Nothing is invented.** Runnable commands are copied verbatim from `scripts` in
|
|
323
|
-
`package.json`. Advertising a command that does not exist means the model calls it,
|
|
324
|
-
fails, and spends the steps you just saved looking for the real one.
|
|
325
|
-
|
|
326
|
-
**The last line matters.** What is listed is the top level and `package.json`, nothing
|
|
327
|
-
inside subfolders. Without saying so, the model treats this as a map of the whole project
|
|
328
|
-
and stops calling `Outline` — at which point the brief costs more than it saves.
|
|
329
|
-
|
|
330
|
-
| Not done | Why |
|
|
331
|
-
|---|---|
|
|
332
|
-
| No `git` subprocess | `.git/HEAD` is read directly. Spawning one freezes startup for seconds on a large repo |
|
|
333
|
-
| No directory walk | Top level **only**. Descending is slow on large repos, and only one line goes in the prompt anyway |
|
|
334
|
-
| Not re-read each turn | Once, at startup. A prompt that changes mid-conversation makes it impossible to tell why an answer changed |
|
|
335
|
-
|
|
336
|
-
It scales with the window — 10 entries and 4 commands at 8k, 24 and 8 on a large one.
|
|
337
|
-
If only one thing survives a narrow window it is the **commands**. The top-level listing
|
|
338
|
-
can be recovered with one `Glob`; "tests run with `npm test`" requires opening
|
|
339
|
-
`package.json`.
|
|
340
|
-
|
|
341
|
-
7ms on a folder with 600 files (`test/project.test.js`).
|
|
342
|
-
|
|
343
|
-
</details>
|
|
266
|
+
> **More** — It adapts to whatever model is attached · Korean models are known before they are experienced · Small windows get a smaller fixed share · On startup it reads what kind of project this folder is
|
|
267
|
+
>
|
|
268
|
+
> **[Models read →](docs/en/models.md#multiple-local-runtimes)**
|
|
344
269
|
|
|
345
270
|
---
|
|
346
271
|
|
|
@@ -351,6 +276,11 @@ Names follow Claude Code / Codex conventions.
|
|
|
351
276
|
| Command | What it does |
|
|
352
277
|
|---|---|
|
|
353
278
|
| `/help` | Command list |
|
|
279
|
+
| `/lang [ko\|en]` | Screen language. Falls back to Korean for anything not translated yet |
|
|
280
|
+
| `/bell [on\|off]` | Ring and set the window title when a turn ends, or when deel needs an answer |
|
|
281
|
+
| `/consult <profile> <question>` | Ask a second model one question. Your current model stays put |
|
|
282
|
+
| `/export` | This conversation as a **one-page HTML report** — asked, changed, verified. Self-contained, opens on any network |
|
|
283
|
+
| `/lsp [on\|off]` | Language servers — what is installed, and whether `Def`/`Refs` are available. `off` turns post-edit diagnostics off only |
|
|
354
284
|
| `/context` | What is consuming the context window |
|
|
355
285
|
| `/ctx [auto\|number]` | Context **length** — re-read it off the model, or set it yourself |
|
|
356
286
|
| `/grade [small\|medium\|large\|auto]` | Model **grade** — how much it does on its own. A different axis from `/ctx` |
|
|
@@ -359,7 +289,10 @@ Names follow Claude Code / Codex conventions.
|
|
|
359
289
|
| `/clear` | Clear the conversation (keeps link and rules) |
|
|
360
290
|
| `/thread [new\|fork\|close\|n]` | Conversation threads — side work in its own context. Link and undo stay shared |
|
|
361
291
|
| `/learned [clear]` | What deel has picked up on its own — commands that work here, this model's habits |
|
|
292
|
+
| `/pin <text>` | Pin a line — folding and compaction **cannot reach it** |
|
|
293
|
+
| `/evidence [file]` | Evidence — what changed, and what proves it. **What is unproven is listed too** |
|
|
362
294
|
| `/model` | Switch connection / model |
|
|
295
|
+
| `/model 카드` | Model card — what this model has actually done here, and what deel changed because of it |
|
|
363
296
|
| `/think <level>` | Reasoning level (`off·low·medium·high·max`) |
|
|
364
297
|
| `/think 배분 <profile>` | Per-stage profile (`even·save·deep`) |
|
|
365
298
|
| `/think 자세히` | Stage table — which stage runs at which level and cap |
|
|
@@ -402,68 +335,9 @@ the conversation.
|
|
|
402
335
|
|
|
403
336
|
Korean IME composition, paste, `Ctrl+A/E` and backspace all keep working.
|
|
404
337
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
### Attaching a file with `@`
|
|
409
|
-
|
|
410
|
-
Write `@` followed by a path and that file is sent along with your message.
|
|
411
|
-
|
|
412
|
-
```
|
|
413
|
-
❯ @src/a.js why is this slow?
|
|
414
|
-
◧ attached src/a.js
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
That removes **one round-trip** — the one where the model has to call `Read` itself. Local
|
|
418
|
-
models are weak at tool calling and that round-trip often misfires: it calls the wrong path,
|
|
419
|
-
or skips the call and invents the contents. You already know which file it is; there is no
|
|
420
|
-
reason to make the model go looking.
|
|
421
|
-
|
|
422
|
-
The hard part is not attaching. It is **not mistaking something else for a file.**
|
|
423
|
-
Things starting with `@` are everywhere.
|
|
424
|
-
|
|
425
|
-
| What you type | What happens |
|
|
426
|
-
|---|---|
|
|
427
|
-
| `@src/a.js` | Attached — only when the path actually exists |
|
|
428
|
-
| `hong@example.com` | Not a mention at all. A letter before the `@` means it is an address |
|
|
429
|
-
| `@media` · `@dataclass` · `@scope/pkg` | Left alone — no such path exists |
|
|
430
|
-
| `@src/` (a directory) | A listing of what is inside is attached |
|
|
431
|
-
| `@"draft report.txt"` | Quote names containing spaces |
|
|
432
|
-
| Outside the working scope | Refused, and the refusal is printed |
|
|
433
|
-
| A CP949 corporate document | Decoded by content and attached correctly |
|
|
434
|
-
|
|
435
|
-
There is one rule: **attach only when the path really exists.** Otherwise the text is left
|
|
436
|
-
exactly as typed, silently — it probably wasn't a mention.
|
|
437
|
-
|
|
438
|
-
Attachments are capped at **25% of the context length** (20,000 tokens at most). Anything larger is attached from the
|
|
439
|
-
top only, and a truncated file is **not marked as already read.** Marking it read would let the
|
|
440
|
-
model edit a part it never saw. Only a fully attached file lets it skip `Read`.
|
|
441
|
-
|
|
442
|
-
Every attachment is announced on screen. Text the user did not type is now in the conversation;
|
|
443
|
-
not showing it would also leave them wondering where the context went.
|
|
444
|
-
|
|
445
|
-
### Interrupting
|
|
446
|
-
|
|
447
|
-
Press **Ctrl+C** to stop the model mid-answer when it is heading the wrong way.
|
|
448
|
-
|
|
449
|
-
```
|
|
450
|
-
❯ rewrite the whole test suite
|
|
451
|
-
◧ Read test/smoke.js
|
|
452
|
-
◧ Read test/loop.test.js
|
|
453
|
-
^C
|
|
454
|
-
⚠ Stopped (after step 2)
|
|
455
|
-
|
|
456
|
-
❯ ▊
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
The conversation stays valid. If the model had announced tool calls, each unanswered one is
|
|
460
|
-
filled with a `stopped by user` result so the call/result pairing holds — a conversation with
|
|
461
|
-
broken pairing is rejected with HTTP 400 on the next request, which would waste the whole
|
|
462
|
-
session. Tools already running finish; **tools not yet started never run.**
|
|
463
|
-
|
|
464
|
-
Pressing Ctrl+C again on an empty line quits.
|
|
465
|
-
|
|
466
|
-
</details>
|
|
338
|
+
> **More** — Attaching a file with @ · Interrupting
|
|
339
|
+
>
|
|
340
|
+
> **[The screen read →](docs/en/interface.md#slash-commands)**
|
|
467
341
|
|
|
468
342
|
---
|
|
469
343
|
|
|
@@ -493,52 +367,9 @@ Don't confuse this with `/mode`. They are separate axes:
|
|
|
493
367
|
If you have explicitly set `/think` or `/mode`, your choice wins. A work mode never
|
|
494
368
|
overrides something a person chose.
|
|
495
369
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
### Switching by itself (Auto mode)
|
|
500
|
-
|
|
501
|
-
You start in **Auto**. Nothing has been decided about what kind of work is coming.
|
|
502
|
-
Every turn, deel reads what you typed, picks the mode that fits, and works in it.
|
|
503
|
-
|
|
504
|
-
```
|
|
505
|
-
❯ why won't the login go through?
|
|
506
|
-
|
|
507
|
-
◉ Debug because your message contained "why won't", "won't"
|
|
508
|
-
Not what you wanted? Type /code to pin a mode yourself.
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
Switching brings **the whole mode** with it — its working protocol, its tool set, its
|
|
512
|
-
reasoning settings. It isn't a label saying "debug mode": the model is actually walked
|
|
513
|
-
through symptom → reproduce → hypothesis → evidence, and in Plan mode `Write` and `Edit`
|
|
514
|
-
are not handed over at all.
|
|
515
|
-
|
|
516
|
-
| When you say | It goes to |
|
|
517
|
-
|---|---|
|
|
518
|
-
| why won't · error · fails · crashes · what's causing | ◉ Debug |
|
|
519
|
-
| plan · roadmap · what order · let's map it out first | ☰ Plan |
|
|
520
|
-
| design · architecture · how should this be structured · how to split | ◈ Architect |
|
|
521
|
-
| what is · explain · how does it work · difference between | ◇ Ask |
|
|
522
|
-
| all of · everything · one by one · to the end · unify | ❋ Orchestrator |
|
|
523
|
-
| fix · add · implement · rename · delete | ◆ Code |
|
|
524
|
-
|
|
525
|
-
**When it's close, it doesn't switch.** "ok", "go on", "that thing from earlier" leave you
|
|
526
|
-
in Auto. So does a near-tie between first and second place — a wrong switch into a read-only
|
|
527
|
-
mode leaves you blocked without knowing *why*. Read-only modes (Plan, Architect, Ask)
|
|
528
|
-
therefore carry a higher bar: "explain this and fix it" routes to Code, not Ask.
|
|
529
|
-
|
|
530
|
-
A switch lasts **one turn only.** The next message is judged fresh.
|
|
531
|
-
A `~` in the status line means it switched by itself; no `~` means you chose it.
|
|
532
|
-
|
|
533
|
-
```
|
|
534
|
-
◎ Auto ← waiting
|
|
535
|
-
~◉ Debug ← this turn only, chosen for you
|
|
536
|
-
◉ Debug ← you typed /debug. It stays.
|
|
537
|
-
```
|
|
538
|
-
|
|
539
|
-
Choosing a mode yourself **pins** it. `/auto` (or `/work auto`) hands the wheel back.
|
|
540
|
-
|
|
541
|
-
</details>
|
|
370
|
+
> **More** — Switching by itself (Auto mode)
|
|
371
|
+
>
|
|
372
|
+
> **[The screen read →](docs/en/interface.md#work-modes)**
|
|
542
373
|
|
|
543
374
|
---
|
|
544
375
|
|
|
@@ -561,202 +392,9 @@ Two things matter here:
|
|
|
561
392
|
- **Beginners do not get fewer safeguards.** Undo, workspace scope and dangerous-command
|
|
562
393
|
blocking are identical. A beginner needs the undo more, not less.
|
|
563
394
|
|
|
564
|
-
|
|
565
|
-
<summary><b>More</b> — The input box · You don't have to type the whole command · The box stays while it works · The picture on the left moves too and 1 more</summary>
|
|
566
|
-
|
|
567
|
-
### The input box
|
|
568
|
-
|
|
569
|
-
Launched in a terminal, **the conversation scrolls normally and an input box is pinned at
|
|
570
|
-
the bottom.** Only the box is erased and redrawn — nothing above it is touched.
|
|
571
|
-
|
|
572
|
-
```
|
|
573
|
-
❊ Grep(console.log)
|
|
574
|
-
└ 3 files · 11 hits
|
|
575
|
-
◈ Edit(src/runner.js)
|
|
576
|
-
└ 1 spot +3-1
|
|
577
|
-
- 12 console.log('시작', 이름)
|
|
578
|
-
+ 12 logger.info({ 단계: '시작', 이름 })
|
|
579
|
-
|
|
580
|
-
▌ Unified log calls to the logger format. One change in runner.js.
|
|
581
|
-
|
|
582
|
-
── 4.2s · 3 tools · ↑3,900 ↓180
|
|
583
|
-
|
|
584
|
-
▏myproject · qwen2.5-coder:7b ▏ ▰▰▱▱▱▱▱▱ 22% ▏ ◎ 종합 · ◇ medium · ⏵⏵ 자동
|
|
585
|
-
╭─────────────────────────────────────────────────────────────────────────────╮
|
|
586
|
-
│ ❯ also shrink the aggregate helpers │
|
|
587
|
-
╰─────────────────────────────────────────────────────────────────────────────╯
|
|
588
|
-
```
|
|
589
|
-
|
|
590
|
-
Terminal scrollback, selection and `Ctrl+F` all keep working, because the conversation is
|
|
591
|
-
never trapped inside a pane of ours. Long input grows the box to as many lines as it needs.
|
|
592
|
-
|
|
593
|
-
**It switches itself off where it would do harm.** Piped or redirected output, `CI` set,
|
|
594
|
-
`TERM=dumb`, or a window under 40 columns: no box, no asking. `deel … | tee log.txt` must
|
|
595
|
-
not become a pile of escape codes. Passing `--tui` does not override a pipe, and `--no-tui`
|
|
596
|
-
turns it off at any time.
|
|
597
|
-
|
|
598
|
-
Line editing stays entirely with Node's readline — Korean IME composition, paste, history,
|
|
599
|
-
Ctrl+A/E, backspace. We only *draw* the string readline is holding. Hand-rolling a line
|
|
600
|
-
editor is how you break IME input first.
|
|
601
|
-
|
|
602
|
-
> **A path taken and abandoned** — the first version borrowed the whole terminal (an
|
|
603
|
-
> alternate screen, like vim) and split it into conversation, changed-files and todo panes.
|
|
604
|
-
> It looked the part, and **every slash command went dead.** Six modules including
|
|
605
|
-
> `commands.js` write straight to the terminal rather than through the screen object, and a
|
|
606
|
-
> full repaint erased their output the instant it appeared. Not "the command didn't run" —
|
|
607
|
-
> "you can't see that it ran", which is worse. Fixing it would mean threading every one of
|
|
608
|
-
> those six through the screen object, plus every one added later, with a silent return of
|
|
609
|
-
> the same symptom if one is missed. So the design went the other way: let the conversation
|
|
610
|
-
> flow, manage only the box. ([`test/box.test.js`](test/box.test.js) spawns a child that
|
|
611
|
-
> pretends to be a terminal, so this one cannot ship again.)
|
|
612
|
-
|
|
613
|
-
---
|
|
614
|
-
|
|
615
|
-
### You don't have to type the whole command
|
|
616
|
-
|
|
617
|
-
There are over thirty commands. The only person who has them memorised is the one who
|
|
618
|
-
wrote them, and even he gets as far as `/mem…` and stops to wonder whether it was `memory`
|
|
619
|
-
or `memo`. If the only recourse at that point is typing `/help` and scanning thirty lines,
|
|
620
|
-
that isn't a command, it's a quiz.
|
|
621
|
-
|
|
622
|
-
So they show up **while you type.**
|
|
623
|
-
|
|
624
|
-
```
|
|
625
|
-
╭─────────────────────────────────────────────────────────────────────────────╮
|
|
626
|
-
│ ❯ /mo │
|
|
627
|
-
╰─────────────────────────────────────────────────────────────────────────────╯
|
|
628
|
-
› /model [이름|list|models] 연결·모델 바꾸기 (이름 일부 · list · models)
|
|
629
|
-
/mode <모드> 승인 정책 — 얼마나 물어보나
|
|
630
|
-
/memory [지우기 <번호>|…] 대화가 끝나도 남는 기억 — 보기·지우기
|
|
631
|
-
```
|
|
632
|
-
|
|
633
|
-
`Tab` fills it in: all the way if only one matches, otherwise **only as far as they all
|
|
634
|
-
agree** (`/mo` + Tab → `/mode`). It doesn't pick one for you, because deleting the wrong
|
|
635
|
-
guess costs more than typing the rest. Commands that take an argument get a trailing space
|
|
636
|
-
so you can keep going.
|
|
637
|
-
|
|
638
|
-
Prefix matches come first and **substring matches follow** — typos cluster in the first
|
|
639
|
-
character, so `/emo` still surfaces `/memory`. The moment you type a space (`/mode auto`)
|
|
640
|
-
the list folds away: the command is already decided.
|
|
641
|
-
|
|
642
|
-
The list sits **below** the box. Putting it inside would push what you are typing upward,
|
|
643
|
-
so you could no longer see it.
|
|
644
|
-
|
|
645
|
-
> No up/down selection. That would have to take over **input history** (up arrow), which
|
|
646
|
-
> is used far more often. What is needed here isn't picking, it's recognising — and once
|
|
647
|
-
> you recognise it, one `Tab` is enough.
|
|
648
|
-
>
|
|
649
|
-
> Commands hidden at the `쉬움` level still surface when you type their prefix. Hidden is
|
|
650
|
-
> not the same as unavailable — someone who knows `/recall` should not be told it doesn't
|
|
651
|
-
> exist because of a display setting.
|
|
652
|
-
|
|
653
|
-
---
|
|
654
|
-
|
|
655
|
-
### The box stays while it works
|
|
656
|
-
|
|
657
|
-
Local models are slow. A single step can take tens of seconds, and if the bottom of the
|
|
658
|
-
screen goes blank for that long, **people assume it hung and hit Ctrl+C** — losing work that
|
|
659
|
-
was nearly done. So the border stays and only the contents change.
|
|
660
|
-
|
|
661
|
-
```
|
|
662
|
-
◧ Read(집계.py)
|
|
663
|
-
└ 6 lines
|
|
664
|
-
|
|
665
|
-
▏myproject · qwen2.5-coder:7b ▏ ▰▱▱▱▱▱▱▱▱▱ 2% ▏ ◎ 종합 · ◇ medium · ⏵⏵ 자동 ▏ ↑3.8k ↓180
|
|
666
|
-
╭─────────────────────────────────────────────────────────────────────────────╮
|
|
667
|
-
│ ⠹ 파일 들여다보는 중… 12초 · 생각 1,240자 · Ctrl+C 중단 │
|
|
668
|
-
╰─────────────────────────────────────────────────────────────────────────────╯
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
The phrase tracks **what is actually happening**. This is not decoration: a message that
|
|
672
|
-
cycles at random stops being read after the second time, and from then on it is worth no
|
|
673
|
-
more than a blank screen. One turn reads like this:
|
|
674
|
-
|
|
675
|
-
```
|
|
676
|
-
머리 굴리는 중 → 파일 들여다보는 중 → 코드 짜는 중 → 답 쓰는 중
|
|
677
|
-
(turning it over) (looking at files) (writing code) (writing the answer)
|
|
678
|
-
```
|
|
679
|
-
|
|
680
|
-
The phrases are Korean, because the interface is. Here is what each set means:
|
|
681
|
-
|
|
682
|
-
| Activity | On screen | Roughly |
|
|
683
|
-
|---|---|---|
|
|
684
|
-
| Thinking | 머리 굴리는 중 · 어떻게 할지 궁리하는 중 · 수 읽는 중 · 따져 보는 중 | turning it over · working out how · reading ahead · weighing it up |
|
|
685
|
-
| `Read` `Grep` `Glob` | 파일 들여다보는 중 · 코드 훑는 중 · 어디 있나 뒤지는 중 · 단서 찾는 중 | looking at files · skimming code · hunting for where it is · looking for a clue |
|
|
686
|
-
| `Write` `Edit` `Append` | 코드 짜는 중 · 고쳐 넣는 중 · 손보는 중 · 한 줄씩 옮기는 중 | writing code · patching it in · touching it up · moving it a line at a time |
|
|
687
|
-
| `Bash` | 명령 돌리는 중 · 터미널 두드리는 중 · 결과 기다리는 중 | running a command · at the terminal · waiting on output |
|
|
688
|
-
| `WebFetch` | 문서 찾아보는 중 · 읽어 오는 중 | looking up docs · fetching |
|
|
689
|
-
| Answering | 답 쓰는 중 · 정리해서 말하는 중 | writing the answer · putting it together |
|
|
690
|
-
| **Past 45 seconds** | 아직 하는 중 · 조금만 더 · 생각보다 오래 걸리는 중 | still going · nearly there · taking longer than expected |
|
|
691
|
-
|
|
692
|
-
Within a category the phrase advances every 4 seconds — text frozen for 30 seconds reads as
|
|
693
|
-
hung too. On the right: **elapsed time**, and while the model is reasoning, **how many
|
|
694
|
-
characters of thinking have arrived**. One number that genuinely increases is what turns
|
|
695
|
-
"still alive" from a claim into a fact.
|
|
696
|
-
|
|
697
|
-
### The picture on the left moves too
|
|
698
|
-
|
|
699
|
-
What spins next to the phrase is not a spinner — it is **a small drawing of the work being
|
|
700
|
-
done right now**.
|
|
701
|
-
|
|
702
|
-
| Doing | One cycle | The picture |
|
|
703
|
-
|---|---|---|
|
|
704
|
-
| Thinking | `⠀⠶⠀` `⠰⣿⠆` `⢾⣿⡷` `⠰⣿⠆` | swells and shrinks |
|
|
705
|
-
| Reading | `⠉⠉⠉` `⠒⠒⠒` `⠤⠤⠤` `⣀⣀⣀` | a scanning line travels down |
|
|
706
|
-
| Writing | `⡼⠭⠧` `⠼⡯⠧` `⠼⠿⡧` `⠼⡭⠧` | **a laptop typing** |
|
|
707
|
-
| Commands | `⠉⠀⠀` `⠉⠈⠀` `⠛⠊⠀` `⠿⠮⠄` | output piles up a line at a time |
|
|
708
|
-
| Answering | `⠉⠀⠀` `⠛⠉⠀` `⠿⠛⠉` `⣿⠿⠛` | text fills up |
|
|
709
|
-
| Web | `⣀⣀⣀` `⣤⣀⣀` `⣶⣤⣀` `⣿⣶⣤` | signal bars grow |
|
|
710
|
-
| Compacting | `⣿⣿⣿` `⣶⣶⣶` `⣤⣤⣤` `⣀⣀⣀` | pressed down into one line |
|
|
711
|
-
| Past 45 seconds | `⠶⠀⠀` `⠰⠆⠀` `⠀⠶⠀` `⠀⠰⠆` | back and forth — "waiting" |
|
|
712
|
-
|
|
713
|
-
Braille only. One braille cell is **2 wide by 4 dots tall**, so three cells make a 6×4 grid
|
|
714
|
-
that is exactly three columns in any terminal. Emoji and `●` `▪` include glyphs that East
|
|
715
|
-
Asian locales measure as two columns, which knocks the border out of line every 90ms.
|
|
716
|
-
|
|
717
|
-
If the drawing does not render, or you use a screen reader, `DEEL_NO_MOTION=1` turns it off
|
|
718
|
-
and you get the old single-cell spinner.
|
|
719
|
-
|
|
720
|
-
### What gets asked, and what just happens
|
|
721
|
-
|
|
722
|
-
Whether your files change **with or without being asked** is the one thing that has to be
|
|
723
|
-
readable at a glance. It sits on the right of the status line at all times.
|
|
724
|
-
|
|
725
|
-
| Indicator | Command | What it asks about |
|
|
726
|
-
|---|---|---|
|
|
727
|
-
| `⏵⏵ 자동 승인` (auto) | `/mode auto` | Nothing is asked. `/undo` is the safety net |
|
|
728
|
-
| `⏵ 위험만 확인` (risky only) | `/mode confirm` | Only irreversible commands. Files change unasked |
|
|
729
|
-
| `⏸ 모두 확인` (everything) | `/mode strict` | Every file change and every command is confirmed first |
|
|
730
|
-
|
|
731
|
-
`/mode` on its own lists all three and marks the current one with ●. The startup header
|
|
732
|
-
spells it out in a sentence, so the glyph is enough from then on.
|
|
733
|
-
|
|
734
|
-
**`Shift+Tab` cycles it without typing.** Each press moves one step and leaves a line
|
|
735
|
-
saying where it went. Whatever you were typing stays put.
|
|
736
|
-
|
|
737
|
-
```
|
|
738
|
-
⏵ 위험만 확인 되돌릴 수 없는 명령만 물어봅니다. 파일은 안 묻고 고칩니다
|
|
739
|
-
자동 승인 → 위험만 확인 · Shift+Tab 으로 계속 바꿉니다
|
|
740
|
-
```
|
|
741
|
-
|
|
742
|
-
The cycle runs **loose → strict** (auto → risky only → everything → auto). A mistaken
|
|
743
|
-
press only makes it ask more; it never drops you into "changes files unasked" in one hit.
|
|
744
|
-
|
|
745
|
-
> That key used to cycle the work mode (`종합`, `코드`, …). The swap is about **who
|
|
746
|
-
> reaches for it more often.** Work mode follows your request on its own, while approval
|
|
747
|
-
> policy is what you want to change mid-task when a particular job deserves a look.
|
|
748
|
-
> Work mode moved to `Ctrl+O`; `/work` still does the same thing.
|
|
749
|
-
|
|
750
|
-
> It used to be the bare word `auto`. Next to `종합` and `medium·절약` it looked like just
|
|
751
|
-
> another mode, and nothing on screen said that one of them meant **files change without
|
|
752
|
-
> asking.**
|
|
395
|
+
> **More** — The input box · You don't have to type the whole command · The box stays while it works · The picture on the left moves too and 1 more
|
|
753
396
|
>
|
|
754
|
-
>
|
|
755
|
-
> like `databricks-gpt-5-6-luna` eats twenty-three columns, and that alone was pushing the
|
|
756
|
-
> approval indicator off the line entirely. Now **the model name shortens first** — you
|
|
757
|
-
> already know what you are running; whether your files change unasked is what you need now.
|
|
758
|
-
|
|
759
|
-
</details>
|
|
397
|
+
> **[The screen read →](docs/en/interface.md#simple-vs-developer)**
|
|
760
398
|
|
|
761
399
|
---
|
|
762
400
|
|
|
@@ -766,7 +404,7 @@ Names and arguments match Claude Code, so skills written for that convention wor
|
|
|
766
404
|
|
|
767
405
|
| Tool | What it does |
|
|
768
406
|
|---|---|
|
|
769
|
-
| `Read` | Read a file (line numbers, `offset`/`limit`, **Excel as CSV**) |
|
|
407
|
+
| `Read` | Read a file (line numbers, `offset`/`limit`, **Excel as CSV, hwpx/docx/pptx as text**) |
|
|
770
408
|
| `Write` | Write / overwrite a file (**several at once via the `files` array**) |
|
|
771
409
|
| `Append` | Append to the end of a file — **how large files get written in pieces** |
|
|
772
410
|
| `Edit` | Replace an exact string (`replace_all`; **several sites at once via the `edits` array**) |
|
|
@@ -782,773 +420,163 @@ Names and arguments match Claude Code, so skills written for that convention wor
|
|
|
782
420
|
| `Verify` | Check that what was built **actually works** |
|
|
783
421
|
| `Task` | Run one chunk of a big job in a **separate context** |
|
|
784
422
|
| `Jobs` | Inspect, read and stop **background commands** — the other half of `Bash`'s `background` |
|
|
423
|
+
| `Def` | **Where a name is defined** — only shown when a language server is installed |
|
|
424
|
+
| `Refs` | **Every place a name is used** — only shown when a language server is installed |
|
|
785
425
|
|
|
786
426
|
Seven tools here are not in Claude Code — `Append`, `Recall`, `Remember`, `Outline`,
|
|
787
427
|
`Verify`, `Task`, `Jobs`. Each tool costs 150-400 tokens of schema on **every request**,
|
|
788
428
|
so a test stops you every time the list grows (`test/loop.test.js`). The last four earned
|
|
789
429
|
their cost; here is why.
|
|
790
430
|
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
### Seeing a project's shape cheaply — `Outline`
|
|
795
|
-
|
|
796
|
-
There used to be only two ways to understand someone else's code. `Glob` gives you paths;
|
|
797
|
-
`Read` pulls a whole file into the window. **The middle was missing.**
|
|
798
|
-
|
|
799
|
-
So the model started editing without knowing what lived where, and re-created functions
|
|
800
|
-
that already existed somewhere else. It had not seen them — which is different from not
|
|
801
|
-
knowing.
|
|
431
|
+
> **More** — Outline · Verify · Task · Def · Refs · Commands that never finish and 9 more
|
|
432
|
+
>
|
|
433
|
+
> **[Tools in depth read →](docs/en/tools.md#tools)**
|
|
802
434
|
|
|
803
|
-
|
|
804
|
-
❉ Outline(src/ui) 12 files · 122 places
|
|
435
|
+
---
|
|
805
436
|
|
|
806
|
-
|
|
807
|
-
46 fn 상자쓸까
|
|
808
|
-
65 class LineScreen
|
|
809
|
-
92 method 줄
|
|
810
|
-
198 class BoxScreen
|
|
811
|
-
```
|
|
437
|
+
## Korean text and Excel
|
|
812
438
|
|
|
813
|
-
|
|
814
|
-
|
|
439
|
+
**A file saved as CP949 is written back as CP949.** The encoding is never changed.
|
|
440
|
+
Excel (`.xlsx`) is read as CSV — read-only.
|
|
815
441
|
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
already there.
|
|
442
|
+
> **More** — Encoding · Excel
|
|
443
|
+
>
|
|
444
|
+
> **[Korean documents and Excel read →](docs/en/documents.md#korean-text-and-excel)**
|
|
820
445
|
|
|
821
|
-
|
|
446
|
+
---
|
|
822
447
|
|
|
823
|
-
|
|
448
|
+
## Serving what you built
|
|
824
449
|
|
|
825
450
|
```
|
|
826
|
-
|
|
827
|
-
```
|
|
828
|
-
|
|
829
|
-
That proves the file **exists**, not that it **works**. An unclosed `<div>`, a
|
|
830
|
-
`src="app.js"` pointing at nothing, a JS file one bracket short — all green.
|
|
831
|
-
|
|
832
|
-
What can be run gets run (`node --check`, `py_compile`); what cannot gets read (HTML tag
|
|
833
|
-
pairing, missing references, CSS braces, JSON).
|
|
451
|
+
❯ /preview
|
|
834
452
|
|
|
453
|
+
▶ Serving http://127.0.0.1:56801/
|
|
454
|
+
showing .
|
|
455
|
+
Edit a file and the page reloads by itself.
|
|
456
|
+
Only this machine can open it (127.0.0.1). No other PC can see it.
|
|
457
|
+
Stop with /preview off · it shuts down when deel exits.
|
|
835
458
|
```
|
|
836
|
-
⏺ Verify 1 broken · 3 checked
|
|
837
|
-
```
|
|
838
|
-
|
|
839
|
-
And the part that matters most — **what could not be checked is reported as such.**
|
|
840
459
|
|
|
841
|
-
|
|
842
|
-
gate and the safety checks live only there, so running commands from here would break the
|
|
843
|
-
strict-mode promise in exactly this one spot. It tells you `npm test` exists instead.
|
|
460
|
+
A browser opens with it. `/preview <folder>` picks what to serve, `/preview off` stops it.
|
|
844
461
|
|
|
845
|
-
|
|
462
|
+
**This is not the same as double-clicking the file (`file://`).** Under `file://` everything
|
|
463
|
+
below is blocked — and the error only shows up in the console while the page stays blank, so
|
|
464
|
+
you end up suspecting your own code. This is a real HTTP server, so it all works:
|
|
846
465
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
466
|
+
| | `file://` | `/preview` |
|
|
467
|
+
|---|---|---|
|
|
468
|
+
| `<script type="module">` · `import` | blocked (CORS) | **works** |
|
|
469
|
+
| `fetch('./data.json')` | blocked | **works** |
|
|
470
|
+
| `new Worker(...)` | blocked | **works** |
|
|
471
|
+
| `WebAssembly.compileStreaming` | blocked (MIME) | **works** |
|
|
472
|
+
| textures · `getImageData` | tainted canvas | **works** |
|
|
473
|
+
| `.glb` / `.gltf` (Three.js) | no MIME type → silently not drawn | **works** |
|
|
851
474
|
|
|
852
|
-
|
|
475
|
+
All seven were run in a real Chrome and confirmed **7/7**.
|
|
853
476
|
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
✓ subtask build the page skeleton done · 2 files · 2 steps
|
|
858
|
-
```
|
|
477
|
+
Apps with a router (React Router and friends) get the first page back when you reload on a
|
|
478
|
+
deep link. Never for requests with an extension (`app.js`) though — returning HTML for a
|
|
479
|
+
missing script dies with `Unexpected token '<'`, which hides the real cause (a typo in a filename).
|
|
859
480
|
|
|
860
|
-
|
|
481
|
+
### It opens exactly as much as it says
|
|
861
482
|
|
|
862
|
-
|
|
863
|
-
|---|---|
|
|
864
|
-
| All in one window | 4,181 chars |
|
|
865
|
-
| Split with `Task` | **2,113 chars** |
|
|
483
|
+
Starting a server means opening your disk to somebody else.
|
|
866
484
|
|
|
867
|
-
|
|
485
|
+
- Bound to **`127.0.0.1` only**. `0.0.0.0` is not available at all — on an office network
|
|
486
|
+
that would let anyone read your source.
|
|
487
|
+
- Port **0** (the kernel hands out a free one). A fixed port steals someone else's.
|
|
488
|
+
- Paths cannot leave the working scope. `../` · `%2e%2e` · double encoding · absolute paths ·
|
|
489
|
+
null bytes · symlinks — eight of these are held shut by tests.
|
|
490
|
+
- **It only serves.** `POST` · `PUT` · `DELETE` are refused with 405.
|
|
491
|
+
- It shuts down when `deel` exits.
|
|
868
492
|
|
|
869
|
-
|
|
870
|
-
same approval mode, is undone **together with** its parent by one `/undo`, and lands in
|
|
871
|
-
the audit log. There is no path for a subtask to edit files under a read-only mode
|
|
872
|
-
(architect, plan, ask) — that is blocked both at the mode level and in the tool list.
|
|
873
|
-
Nesting stops at two levels.
|
|
493
|
+
---
|
|
874
494
|
|
|
875
|
-
|
|
495
|
+
## Skills and plugins
|
|
876
496
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
to mean waiting 120 seconds and then a kill, leaving one line on screen.
|
|
497
|
+
**deel does not carry skills with it.** On startup it scans the machine it is running on and uses
|
|
498
|
+
whatever is there. On a clean PC: zero. On a PC with skills installed: those skills.
|
|
880
499
|
|
|
881
500
|
```
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
501
|
+
project ./.deel/skills ./.claude/skills ./.deel/commands ./.claude/commands
|
|
502
|
+
user ~/.deel/skills ~/.claude/skills ~/.claude/commands
|
|
503
|
+
plugins ~/.claude/plugins/** ~/.deel/plugins/**
|
|
885
504
|
```
|
|
886
505
|
|
|
887
|
-
|
|
888
|
-
and calls again — which stalls the whole turn. **There was no way at all to start what
|
|
889
|
-
you built and check it.** `Verify` gets you as far as "the syntax is valid"; whether it
|
|
890
|
-
actually comes up requires bringing it up.
|
|
506
|
+
Reads the Claude Code format: `SKILL.md` with YAML front matter, `commands/*.md`, `$ARGUMENTS`.
|
|
891
507
|
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
508
|
+
> **More** — Loaded in three stages · Fetching plugins · Deliberately not included
|
|
509
|
+
>
|
|
510
|
+
> **[Extending read →](docs/en/extend.md#skills-and-plugins)**
|
|
895
511
|
|
|
896
|
-
|
|
897
|
-
└ 1군데 (1 site)
|
|
512
|
+
---
|
|
898
513
|
|
|
899
|
-
|
|
900
|
-
└ 도는중 · 24초 (running · 24s)
|
|
514
|
+
### The hidden latency of local models — keeping the prefix cache alive
|
|
901
515
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
516
|
+
Ollama and llama.cpp reuse computation **only while the request starts the same way as the
|
|
517
|
+
last one.** Change one early character and everything after it — the entire conversation —
|
|
518
|
+
is recomputed. This is the usual hidden reason long local sessions feel slower and slower,
|
|
519
|
+
and it never shows up anywhere, because it is not an error.
|
|
905
520
|
|
|
906
|
-
|
|
521
|
+
deel routes every message to the right mode automatically, and that mode instruction used to
|
|
522
|
+
sit **early** in the prompt — every mode switch broke the whole cache. So the stable parts
|
|
523
|
+
(rules, folder, project fingerprint, user rules, memory, skills) are frozen at the front and
|
|
524
|
+
the per-turn parts (mode, pins) go last. A test pins this order down (`test/cache.test.js`).
|
|
907
525
|
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
526
|
+
Ollama also gets `keep_alive: 60m` — with the 5-minute default, the model unloads while you
|
|
527
|
+
glance at another window, and the first message after you come back recomputes everything.
|
|
528
|
+
Override with `DEEL_KEEP_ALIVE`. If you run llama.cpp directly, `--cache-reuse 256` on the
|
|
529
|
+
server side does the same job.
|
|
912
530
|
|
|
913
|
-
|
|
914
|
-
▶ Bash(npm run dev)
|
|
915
|
-
└ 띄우자마자 끝났습니다 (종료코드 1).
|
|
916
|
-
(exited immediately, exit code 1)
|
|
917
|
-
```
|
|
531
|
+
## Reasoning effort
|
|
918
532
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
| Handed to the model | 4,000 chars. This **must** be a different number from the one above |
|
|
925
|
-
| On stop | Waits for the dying output, and returns only once the process is **actually dead** |
|
|
926
|
-
| Argument names | Korean and English both accepted (`번호`/`job`, `끝내기`/`stop`). Unrecognized ones **are reported** |
|
|
927
|
-
| Count | Eight running. Finished jobs keep the most recent eight, and evictions **are stated** |
|
|
928
|
-
|
|
929
|
-
Why two different caps: make them equal and every overflow of a `watch` job means
|
|
930
|
-
one `Jobs` read dumps 256KB into the window. On an 8k model that single read ends
|
|
931
|
-
the window.
|
|
932
|
-
|
|
933
|
-
**Stopping a job does not close its pipes immediately.** At the moment the kill is
|
|
934
|
-
issued there is still unread data in the pipe, and the last few lines before a
|
|
935
|
-
death are the ones that matter — the stack trace a server leaves on the way down.
|
|
936
|
-
Printing `last output:` and then withholding the last output is worse than not
|
|
937
|
-
printing it. It also waits until the process is **confirmed dead** before dropping
|
|
938
|
-
it from the list: dropping a live one means it can never be named again, which is
|
|
939
|
-
the exact state this feature exists to prevent.
|
|
940
|
-
|
|
941
|
-
Finished jobs are not dropped right away — they are kept so their final output can
|
|
942
|
-
be read. Only the most recent eight survive; otherwise thirty short commands leave
|
|
943
|
-
thirty entries, each holding up to 256KB.
|
|
944
|
-
|
|
945
|
-
**Argument names are accepted in both Korean and English.** Models frequently
|
|
946
|
-
translate Korean parameter names into English — not a guess, something this repo
|
|
947
|
-
already hit (`Task` accepts both `목적` and `purpose`). `Jobs` did not, which meant:
|
|
533
|
+
One answer means several model calls, and **each needs a different amount of thinking.**
|
|
534
|
+
All-high is slow; all-low wanders off.
|
|
535
|
+
|
|
536
|
+
The default is **one line**. What you want to know is how hard it is thinking right now,
|
|
537
|
+
not a stage table.
|
|
948
538
|
|
|
949
539
|
```
|
|
950
|
-
|
|
540
|
+
$ /think
|
|
541
|
+
|
|
542
|
+
추론 강도 medium (첫 판단 medium · 이어가기 low · 막혔을 때 high)
|
|
543
|
+
더 세게 /think high 더 빠르게 /think low
|
|
951
544
|
```
|
|
952
545
|
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
546
|
+
| Profile | Character |
|
|
547
|
+
|---|---|
|
|
548
|
+
| `even` | Same effort everywhere — predictable, slower |
|
|
549
|
+
| `save` (default) | Hard on the first decision only |
|
|
550
|
+
| `deep` | Everything one notch up — for hard work |
|
|
958
551
|
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
**started in its own process group** — after the fact there is no way to name a
|
|
963
|
-
grandchild at all. Skip that and deel says "killed 3" while the server keeps running.
|
|
552
|
+
Set the profile with `/think 배분 절약`. **Level and profile are different axes, so the
|
|
553
|
+
commands were split** — `/think high` and `/think save` used to set different things under
|
|
554
|
+
one name, which made the screen unreadable.
|
|
964
555
|
|
|
965
|
-
|
|
966
|
-
running. Next time you start a dev server you get "port already in use" with **no way to
|
|
967
|
-
find what is holding it**. So `test/jobs.test.js` verifies the process actually died, via
|
|
968
|
-
a file the child keeps appending to.
|
|
556
|
+
The stage table moved to `/think 자세히` (the default at developer level).
|
|
969
557
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
with nothing in the log to explain it.
|
|
558
|
+
```
|
|
559
|
+
$ /think 자세히
|
|
973
560
|
|
|
974
|
-
|
|
561
|
+
추론 강도 medium (첫 판단 medium · 이어가기 low · 막혔을 때 high)
|
|
562
|
+
배분 절약 첫 판단만 세게, 이어가기는 얕게 — 대개 이게 낫습니다
|
|
975
563
|
|
|
976
|
-
|
|
977
|
-
|
|
564
|
+
단계 강도 출력상한 언제
|
|
565
|
+
첫 판단 · medium 15,549 무엇을 할지 정하는 자리
|
|
566
|
+
이어가기 ↓ low 13,605 도구 결과를 읽고 다음 한 수
|
|
567
|
+
막혔을 때 ↑ high 16,384 직전 도구가 오류를 냄
|
|
978
568
|
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
└ 2개 파일 · 3군데 (2 files · 3 sites)
|
|
982
|
-
✓ src/app.js · 2군데
|
|
983
|
-
✓ src/style.css · 1군데
|
|
569
|
+
출력 상한은 16,384 (모르는 값이라 기본값) 안에서 나눕니다 — /out
|
|
570
|
+
컨텍스트 40,960 · 지금 찬 양 2,087
|
|
984
571
|
```
|
|
985
572
|
|
|
986
|
-
|
|
987
|
-
|
|
573
|
+
That second-to-last line exists for a reason: **when all three caps are equal, it is the
|
|
574
|
+
only thing that says whether that is correct.** A low known cap makes them equal, and that
|
|
575
|
+
is fine. For a while all three read `16,384` always — which meant the table said nothing.
|
|
988
576
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
| One failure | The rest still run. Stopping at the first failure re-adds the round trips this was meant to remove |
|
|
993
|
-
| On failure | "Resend only what failed — **and `Read` the file again first**" |
|
|
994
|
-
| Undo | Still **one turn**. Six sites in one file is one `/undo` |
|
|
995
|
-
| Single-site form | The result shape is byte-for-byte unchanged |
|
|
996
|
-
|
|
997
|
-
It reports `2 files · 3 sites` rather than a single number. Editing one file at six sites
|
|
998
|
-
is normal, so "3 files" would be false — and once the screen stops matching what you can
|
|
999
|
-
count yourself, you stop trusting the screen.
|
|
1000
|
-
|
|
1001
|
-
### Finding past conversations, and remembering decisions
|
|
1002
|
-
|
|
1003
|
-
deel writes every conversation to `.deel/sessions/*.jsonl`. Until now all you could do was
|
|
1004
|
-
list them — **a record you cannot search is the same as no record.**
|
|
1005
|
-
|
|
1006
|
-
```
|
|
1007
|
-
$ /recall 인코딩을 어떻게
|
|
1008
|
-
|
|
1009
|
-
2026-08-01 10:15 모델 20260801-101500
|
|
1010
|
-
CP949 인코딩 문제입니다. 읽을 때 인코딩을 재서 그대로 되돌려 쓰도록…
|
|
1011
|
-
```
|
|
1012
|
-
|
|
1013
|
-
Korean particles are handled: `인코딩을` also matches `인코딩`. A morphological analyser is
|
|
1014
|
-
out of the question (zero dependencies), so particle-looking tails are stripped and **both**
|
|
1015
|
-
forms are searched. No index is built — an index inevitably goes stale, and **a stale index is
|
|
1016
|
-
worse than none** ("not found" reads as "never happened"). Instead every search reports how
|
|
1017
|
-
much it read and what it could not.
|
|
1018
|
-
|
|
1019
|
-
`Recall` is also a **tool**. Left as a human-only command, "do it the way we decided last
|
|
1020
|
-
time" leaves the model nothing to do but ask again.
|
|
1021
|
-
|
|
1022
|
-
**Memory (`/memory`) is a different thing.** Recall has to be *searched*; memory is *already
|
|
1023
|
-
there*. Things you cannot re-explain every session go here.
|
|
1024
|
-
|
|
1025
|
-
```
|
|
1026
|
-
$ /memory
|
|
1027
|
-
|
|
1028
|
-
1 사내 문서는 CP949 로 읽고 CP949 로 되돌려 쓴다
|
|
1029
|
-
2 검증할 때 7080 포트는 쓰지 않는다
|
|
1030
|
-
|
|
1031
|
-
2줄 · 약 30토큰이 매 요청마다 함께 나갑니다
|
|
1032
|
-
파일 .deel/memory.md — 직접 고치셔도 됩니다
|
|
1033
|
-
```
|
|
1034
|
-
|
|
1035
|
-
`.deel/memory.md` is **prose a human edits**, not a database. That matters: a line the model
|
|
1036
|
-
got wrong ships on every request and keeps being wrong. **A wrong memory is worse than none.**
|
|
1037
|
-
So `/memory 지우기 2` deletes one.
|
|
1038
|
-
|
|
1039
|
-
Because it ships on every request it is bounded: 400 chars per line, 60 lines, 6,000 chars
|
|
1040
|
-
total. Overflow drops the oldest and says so. `/context` shows its line count and tokens.
|
|
1041
|
-
|
|
1042
|
-
### Repeatable procedures become skills
|
|
1043
|
-
|
|
1044
|
-
When a multi-step job finishes and it is something that will come up again, the model writes
|
|
1045
|
-
the procedure to `.deel/skills/<name>/SKILL.md`. Next session it appears in the skill list;
|
|
1046
|
-
when it turns out to be wrong somewhere, the model edits that file.
|
|
1047
|
-
|
|
1048
|
-
No new tool needed — the existing `Write` writes it and the existing skill sweep reads it.
|
|
1049
|
-
|
|
1050
|
-
### Large files are written in pieces — `Append`
|
|
1051
|
-
|
|
1052
|
-
A model with a 4k output cap still has to be able to write a 2,000-line file, eight pieces at
|
|
1053
|
-
a time. Stitching with `Edit` does not work in practice — HTML repeats anchors like `</div>`,
|
|
1054
|
-
so the match comes back as "found in several places", and a longer anchor eats the tokens that
|
|
1055
|
-
should have gone into the body.
|
|
1056
|
-
|
|
1057
|
-
`Write` to create, `Append` to continue. Encoding follows `Write` (CP949 for corporate
|
|
1058
|
-
documents, the BOM on a `.csv` is preserved). The undo snapshot is taken **only on the first
|
|
1059
|
-
`Append`** — eight appends must not leave eight copies in the history, or there is no single
|
|
1060
|
-
point to revert to.
|
|
1061
|
-
|
|
1062
|
-
```
|
|
1063
|
-
⏺ Write(dashboard.html)
|
|
1064
|
-
└ ⚠ wrote only as far as it arrived — 632 lines
|
|
1065
|
-
↻ the reply hit the cap — retrying with 9,984 → 16,384
|
|
1066
|
-
⏺ Append(dashboard.html)
|
|
1067
|
-
└ +567 lines · 1,199 total
|
|
1068
|
-
|
|
1069
|
-
✓ dashboard.html · 1,199 lines · 97.7KB
|
|
1070
|
-
```
|
|
1071
|
-
|
|
1072
|
-
That last line matters. If the file does not exist and the model says "created it", you would
|
|
1073
|
-
believe it. **The real file is measured at the end of the turn.**
|
|
1074
|
-
|
|
1075
|
-
### Checklists
|
|
1076
|
-
|
|
1077
|
-
Keeps the model from losing its place on multi-step work. The list is redrawn whenever the
|
|
1078
|
-
model updates it.
|
|
1079
|
-
|
|
1080
|
-
```
|
|
1081
|
-
☰ Todo 1/3 done ← just finished 1
|
|
1082
|
-
|
|
1083
|
-
✓ unify log format
|
|
1084
|
-
▶ fix the tests
|
|
1085
|
-
☐ update the docs
|
|
1086
|
-
```
|
|
1087
|
-
|
|
1088
|
-
Only one item may be **in progress** at a time; setting two is refused. Holding several at
|
|
1089
|
-
once is how nothing gets finished.
|
|
1090
|
-
|
|
1091
|
-
### Read-only tools run together
|
|
1092
|
-
|
|
1093
|
-
When the model asks for three `Read` calls at once, all three run **concurrently** — sweeping
|
|
1094
|
-
five files costs about what reading one costs.
|
|
1095
|
-
|
|
1096
|
-
```
|
|
1097
|
-
◧ Read src/a.js ◧ Read src/b.js ◧ Read src/c.js together
|
|
1098
|
-
```
|
|
1099
|
-
|
|
1100
|
-
Only `Read`, `Glob`, `Grep`, `Skill` and `WebFetch` are eligible. `Write`, `Edit` and `Bash`
|
|
1101
|
-
always run one at a time — two concurrent writes to one file scramble the undo snapshot
|
|
1102
|
-
order, and `Bash` can do anything. Results come back **in the order the model asked for
|
|
1103
|
-
them**, even when they finish out of order; shuffled results confuse the model about which
|
|
1104
|
-
result belongs to which call.
|
|
1105
|
-
|
|
1106
|
-
### Edits survive small mistakes
|
|
1107
|
-
|
|
1108
|
-
Models routinely get whitespace, indentation and line endings wrong. deel relaxes matching in
|
|
1109
|
-
stages but **refuses outright when the match is ambiguous** — silently editing the wrong place is
|
|
1110
|
-
far worse than not finding it.
|
|
1111
|
-
|
|
1112
|
-
```
|
|
1113
|
-
exact → ignore trailing space / CRLF → ignore indentation → ignore all whitespace
|
|
1114
|
-
```
|
|
1115
|
-
|
|
1116
|
-
Measured with `npm run bench`:
|
|
1117
|
-
|
|
1118
|
-
| | Success | Wrong place edited |
|
|
1119
|
-
|---|---|---|
|
|
1120
|
-
| Exact match only | 20% | 0 |
|
|
1121
|
-
| Staged relaxation | **100%** | **0** |
|
|
1122
|
-
|
|
1123
|
-
On failure it points at the closest line in the file.
|
|
1124
|
-
|
|
1125
|
-
### It shows you what it changed
|
|
1126
|
-
|
|
1127
|
-
`auto` mode edits without asking. That is the speed of this tool — but if all that reaches the
|
|
1128
|
-
screen is `1 spot`, you move on without knowing what happened. Undo is the safety net, and
|
|
1129
|
-
**you cannot decide whether to undo something you never saw.** So every `Edit` and `Write` is
|
|
1130
|
-
followed by the changed lines themselves.
|
|
1131
|
-
|
|
1132
|
-
```
|
|
1133
|
-
◈ Edit(src/runner.js)
|
|
1134
|
-
└ 1 spot +1 −2
|
|
1135
|
-
|
|
1136
|
-
11 const id = job.id;
|
|
1137
|
-
- console.log("start: " + id);
|
|
1138
|
-
- console.log(" opts " + JSON.stringify(opts));
|
|
1139
|
-
+ 12 logger.info('start', { id, opts });
|
|
1140
|
-
13 return run(job);
|
|
1141
|
-
```
|
|
1142
|
-
|
|
1143
|
-
The `+1 −2` next to the summary is how many lines were added and removed.
|
|
1144
|
-
|
|
1145
|
-
- **Removed lines carry no line number.** They no longer exist in the file. Printing the old
|
|
1146
|
-
number put it directly under a context line's new number — two different files' numbering in
|
|
1147
|
-
one column. Line 8 really did appear twice on screen.
|
|
1148
|
-
- If only the line endings changed (CRLF/LF), it says so. Otherwise every visually identical
|
|
1149
|
-
line shows as changed and the real edit is impossible to find.
|
|
1150
|
-
- Large files are compared after trimming the identical head and tail. If it is still too big,
|
|
1151
|
-
exact matching is abandoned for "this whole block changed" — a rough answer now beats an
|
|
1152
|
-
exact one later.
|
|
1153
|
-
|
|
1154
|
-
How many lines are shown depends on the level. Forty lines at someone's first launch means none get read.
|
|
1155
|
-
|
|
1156
|
-
| | Simple | Developer |
|
|
1157
|
-
|---|---|---|
|
|
1158
|
-
| After a tool call | 14 lines | 40 lines |
|
|
1159
|
-
| `/diff <file>` | 60 lines | 200 lines |
|
|
1160
|
-
|
|
1161
|
-
### `/diff` — everything changed this session
|
|
1162
|
-
|
|
1163
|
-
Those lines scroll away. `/diff` collects every file touched this session onto one page.
|
|
1164
|
-
|
|
1165
|
-
```
|
|
1166
|
-
$ /diff
|
|
1167
|
-
|
|
1168
|
-
── files changed this session ─────────────────────────────
|
|
1169
|
-
src/runner.js +12 −7 3×
|
|
1170
|
-
src/logger.js +40 −0
|
|
1171
|
-
──────────────────────────────────────────────────────────
|
|
1172
|
-
2 files +52 −7
|
|
1173
|
-
|
|
1174
|
-
/diff <file> for detail, /undo to revert
|
|
1175
|
-
```
|
|
1176
|
-
|
|
1177
|
-
`/diff <file>` compares **the state at the start of the session against now.** Even after
|
|
1178
|
-
three edits, what you want to know is "what is different from before I asked", not what the
|
|
1179
|
-
last edit did. That original state comes from the earliest undo snapshot.
|
|
1180
|
-
|
|
1181
|
-
`/diff` is **in the simple level's command list.** As long as `auto` edits without asking,
|
|
1182
|
-
a beginner needs a way to see what changed more than anyone.
|
|
1183
|
-
|
|
1184
|
-
</details>
|
|
1185
|
-
|
|
1186
|
-
---
|
|
1187
|
-
|
|
1188
|
-
## Korean text and Excel
|
|
1189
|
-
|
|
1190
|
-
**A file saved as CP949 is written back as CP949.** The encoding is never changed.
|
|
1191
|
-
Excel (`.xlsx`) is read as CSV — read-only.
|
|
1192
|
-
|
|
1193
|
-
<details>
|
|
1194
|
-
<summary><b>More</b> — Encoding · Excel</summary>
|
|
1195
|
-
|
|
1196
|
-
### Encoding — written back the way it was read
|
|
1197
|
-
|
|
1198
|
-
Corporate documents are often not UTF-8. Files saved by old Windows Notepad in a legacy
|
|
1199
|
-
codepage (CP949 in Korea, CP932 in Japan, GBK in China) are still around. Reading one as
|
|
1200
|
-
UTF-8 garbles it completely: `한글` becomes `�ѱ�`.
|
|
1201
|
-
|
|
1202
|
-
Writing is the dangerous part. Read it garbled, save it as UTF-8, and the original is gone.
|
|
1203
|
-
So there is one rule: **write it back in the encoding it was read in.**
|
|
1204
|
-
|
|
1205
|
-
Which encoding that is comes from **the file's contents, not the machine's settings.**
|
|
1206
|
-
Each candidate is decoded strictly, then scored on whether the result looks like real text
|
|
1207
|
-
written in that encoding. So the same CP949 document reads identically on Ubuntu, on a US
|
|
1208
|
-
Windows machine, and on a Korean one.
|
|
1209
|
-
|
|
1210
|
-
```
|
|
1211
|
-
› Read report.txt
|
|
1212
|
-
└ 4 lines · CP949
|
|
1213
|
-
```
|
|
1214
|
-
|
|
1215
|
-
If you try to insert a character that encoding **cannot hold**, it refuses instead of saving.
|
|
1216
|
-
|
|
1217
|
-
```
|
|
1218
|
-
› Edit report.txt note → note 🚀
|
|
1219
|
-
└ This file is CP949, and you are inserting a character that encoding does not have: 🚀
|
|
1220
|
-
```
|
|
1221
|
-
|
|
1222
|
-
Silently substituting question marks would be worse than not writing at all.
|
|
1223
|
-
Newly created files are UTF-8.
|
|
1224
|
-
|
|
1225
|
-
Command output is handled the same way. A Windows console is not UTF-8, so taking `Bash`
|
|
1226
|
-
output as utf8 garbles non-ASCII text. It is collected as bytes and decoded afterwards.
|
|
1227
|
-
|
|
1228
|
-
**Undo snapshots are stored as bytes too.** They used to be stored as UTF-8 text, so undoing
|
|
1229
|
-
a CP949 file brought back `가나다` (bytes `b0a1 b3aa b4d9`) as six U+FFFD characters — **the
|
|
1230
|
-
safety net itself destroyed the original bytes.** Now every snapshot is round-tripped through
|
|
1231
|
-
UTF-8 first; anything that does not come back identical is stored as base64 and restored
|
|
1232
|
-
byte-exact.
|
|
1233
|
-
|
|
1234
|
-
### Excel — read as CSV
|
|
1235
|
-
|
|
1236
|
-
An Excel file is a compressed archive, not text, so normally you get "this is a binary file"
|
|
1237
|
-
and somebody has to export a CSV by hand. `Read` just does it.
|
|
1238
|
-
|
|
1239
|
-
```
|
|
1240
|
-
› Read report.xlsx
|
|
1241
|
-
└ 3 sheets · 128 rows · unpacked directly
|
|
1242
|
-
```
|
|
1243
|
-
|
|
1244
|
-
- **Still zero dependencies.** An xlsx is a zip full of XML, so Node's built-in `zlib` is enough.
|
|
1245
|
-
- Every sheet is returned. Hidden sheets too, marked as hidden.
|
|
1246
|
-
- Dates come back as dates, not serial numbers — the cell format is read to decide.
|
|
1247
|
-
- Formulas come back as **computed values**, and error values like `#REF!` are not dropped.
|
|
1248
|
-
|
|
1249
|
-
**Password-protected files and legacy `.xls`** are handed to Excel itself; those cannot be
|
|
1250
|
-
unpacked directly. You are asked for the password at that point.
|
|
1251
|
-
|
|
1252
|
-
The password is **not stored anywhere**:
|
|
1253
|
-
|
|
1254
|
-
- not in the config file
|
|
1255
|
-
- not in the session log
|
|
1256
|
-
- not in the audit log
|
|
1257
|
-
- not as a command-line argument (other people can see your command lines)
|
|
1258
|
-
|
|
1259
|
-
The only path out is the child process's stdin, and a test asserts that this stays true.
|
|
1260
|
-
Extracted intermediate files are deleted after use.
|
|
1261
|
-
|
|
1262
|
-
> **Excel files are read-only here.** `Edit` and `Write` refuse them, and say why and what
|
|
1263
|
-
> to do instead. Round-tripping a file with formatting, formulas and charts through CSV
|
|
1264
|
-
> always loses something. Better not to write than to write knowing you'll lose data.
|
|
1265
|
-
|
|
1266
|
-
</details>
|
|
1267
|
-
|
|
1268
|
-
---
|
|
1269
|
-
|
|
1270
|
-
## Serving what you built
|
|
1271
|
-
|
|
1272
|
-
```
|
|
1273
|
-
❯ /preview
|
|
1274
|
-
|
|
1275
|
-
▶ Serving http://127.0.0.1:56801/
|
|
1276
|
-
showing .
|
|
1277
|
-
Edit a file and the page reloads by itself.
|
|
1278
|
-
Only this machine can open it (127.0.0.1). No other PC can see it.
|
|
1279
|
-
Stop with /preview off · it shuts down when deel exits.
|
|
1280
|
-
```
|
|
1281
|
-
|
|
1282
|
-
A browser opens with it. `/preview <folder>` picks what to serve, `/preview off` stops it.
|
|
1283
|
-
|
|
1284
|
-
**This is not the same as double-clicking the file (`file://`).** Under `file://` everything
|
|
1285
|
-
below is blocked — and the error only shows up in the console while the page stays blank, so
|
|
1286
|
-
you end up suspecting your own code. This is a real HTTP server, so it all works:
|
|
1287
|
-
|
|
1288
|
-
| | `file://` | `/preview` |
|
|
1289
|
-
|---|---|---|
|
|
1290
|
-
| `<script type="module">` · `import` | blocked (CORS) | **works** |
|
|
1291
|
-
| `fetch('./data.json')` | blocked | **works** |
|
|
1292
|
-
| `new Worker(...)` | blocked | **works** |
|
|
1293
|
-
| `WebAssembly.compileStreaming` | blocked (MIME) | **works** |
|
|
1294
|
-
| textures · `getImageData` | tainted canvas | **works** |
|
|
1295
|
-
| `.glb` / `.gltf` (Three.js) | no MIME type → silently not drawn | **works** |
|
|
1296
|
-
|
|
1297
|
-
All seven were run in a real Chrome and confirmed **7/7**.
|
|
1298
|
-
|
|
1299
|
-
Apps with a router (React Router and friends) get the first page back when you reload on a
|
|
1300
|
-
deep link. Never for requests with an extension (`app.js`) though — returning HTML for a
|
|
1301
|
-
missing script dies with `Unexpected token '<'`, which hides the real cause (a typo in a filename).
|
|
1302
|
-
|
|
1303
|
-
### It opens exactly as much as it says
|
|
1304
|
-
|
|
1305
|
-
Starting a server means opening your disk to somebody else.
|
|
1306
|
-
|
|
1307
|
-
- Bound to **`127.0.0.1` only**. `0.0.0.0` is not available at all — on an office network
|
|
1308
|
-
that would let anyone read your source.
|
|
1309
|
-
- Port **0** (the kernel hands out a free one). A fixed port steals someone else's.
|
|
1310
|
-
- Paths cannot leave the working scope. `../` · `%2e%2e` · double encoding · absolute paths ·
|
|
1311
|
-
null bytes · symlinks — eight of these are held shut by tests.
|
|
1312
|
-
- **It only serves.** `POST` · `PUT` · `DELETE` are refused with 405.
|
|
1313
|
-
- It shuts down when `deel` exits.
|
|
1314
|
-
|
|
1315
|
-
---
|
|
1316
|
-
|
|
1317
|
-
## Skills and plugins
|
|
1318
|
-
|
|
1319
|
-
**deel does not carry skills with it.** On startup it scans the machine it is running on and uses
|
|
1320
|
-
whatever is there. On a clean PC: zero. On a PC with skills installed: those skills.
|
|
1321
|
-
|
|
1322
|
-
```
|
|
1323
|
-
project ./.deel/skills ./.claude/skills ./.deel/commands ./.claude/commands
|
|
1324
|
-
user ~/.deel/skills ~/.claude/skills ~/.claude/commands
|
|
1325
|
-
plugins ~/.claude/plugins/** ~/.deel/plugins/**
|
|
1326
|
-
```
|
|
1327
|
-
|
|
1328
|
-
Reads the Claude Code format: `SKILL.md` with YAML front matter, `commands/*.md`, `$ARGUMENTS`.
|
|
1329
|
-
|
|
1330
|
-
<details>
|
|
1331
|
-
<summary><b>More</b> — Loaded in three stages · Fetching plugins · Deliberately not included</summary>
|
|
1332
|
-
|
|
1333
|
-
### Loaded in three stages
|
|
1334
|
-
|
|
1335
|
-
Loading everything would blow the context window.
|
|
1336
|
-
|
|
1337
|
-
| Stage | What | Cost |
|
|
1338
|
-
|---|---|---|
|
|
1339
|
-
| 1 | Name + one-line description in the prompt | ~1,800 tokens for 40 skills |
|
|
1340
|
-
| 2 | Body of the one the model picks via `Skill` | one at a time |
|
|
1341
|
-
| 3 | Files that body references, via `Read` | on demand |
|
|
1342
|
-
|
|
1343
|
-
### Fetching plugins
|
|
1344
|
-
|
|
1345
|
-
```bash
|
|
1346
|
-
# on a connected machine
|
|
1347
|
-
/plugin install affaan-m/ECC # git clone, or tarball when git is absent
|
|
1348
|
-
/plugin pack import.zip # bundle, excluding executable scripts
|
|
1349
|
-
|
|
1350
|
-
# on the air-gapped machine — just unzip
|
|
1351
|
-
unzip import.zip -d ~/.deel/plugins/
|
|
1352
|
-
```
|
|
1353
|
-
|
|
1354
|
-
`/plugin pack` omits `.js` `.sh` `.ps1` `.py` and friends, and includes a plain-text manifest
|
|
1355
|
-
with a licence table — ready to hand to a security reviewer.
|
|
1356
|
-
|
|
1357
|
-
### Deliberately not included
|
|
1358
|
-
|
|
1359
|
-
| | Why |
|
|
1360
|
-
|---|---|
|
|
1361
|
-
| hooks | Executable scripts — fails import review, widens the blast radius of autonomy |
|
|
1362
|
-
| sub-agents | Doubles model calls against a gateway quota |
|
|
1363
|
-
| MCP | A separate protocol; a project of its own |
|
|
1364
|
-
|
|
1365
|
-
</details>
|
|
1366
|
-
|
|
1367
|
-
---
|
|
1368
|
-
|
|
1369
|
-
## Reasoning effort
|
|
1370
|
-
|
|
1371
|
-
One answer means several model calls, and **each needs a different amount of thinking.**
|
|
1372
|
-
All-high is slow; all-low wanders off.
|
|
1373
|
-
|
|
1374
|
-
The default is **one line**. What you want to know is how hard it is thinking right now,
|
|
1375
|
-
not a stage table.
|
|
1376
|
-
|
|
1377
|
-
```
|
|
1378
|
-
$ /think
|
|
1379
|
-
|
|
1380
|
-
추론 강도 medium (첫 판단 medium · 이어가기 low · 막혔을 때 high)
|
|
1381
|
-
더 세게 /think high 더 빠르게 /think low
|
|
1382
|
-
```
|
|
1383
|
-
|
|
1384
|
-
| Profile | Character |
|
|
1385
|
-
|---|---|
|
|
1386
|
-
| `even` | Same effort everywhere — predictable, slower |
|
|
1387
|
-
| `save` (default) | Hard on the first decision only |
|
|
1388
|
-
| `deep` | Everything one notch up — for hard work |
|
|
1389
|
-
|
|
1390
|
-
Set the profile with `/think 배분 절약`. **Level and profile are different axes, so the
|
|
1391
|
-
commands were split** — `/think high` and `/think save` used to set different things under
|
|
1392
|
-
one name, which made the screen unreadable.
|
|
1393
|
-
|
|
1394
|
-
The stage table moved to `/think 자세히` (the default at developer level).
|
|
1395
|
-
|
|
1396
|
-
```
|
|
1397
|
-
$ /think 자세히
|
|
1398
|
-
|
|
1399
|
-
추론 강도 medium (첫 판단 medium · 이어가기 low · 막혔을 때 high)
|
|
1400
|
-
배분 절약 첫 판단만 세게, 이어가기는 얕게 — 대개 이게 낫습니다
|
|
1401
|
-
|
|
1402
|
-
단계 강도 출력상한 언제
|
|
1403
|
-
첫 판단 · medium 15,549 무엇을 할지 정하는 자리
|
|
1404
|
-
이어가기 ↓ low 13,605 도구 결과를 읽고 다음 한 수
|
|
1405
|
-
막혔을 때 ↑ high 16,384 직전 도구가 오류를 냄
|
|
1406
|
-
|
|
1407
|
-
출력 상한은 16,384 (모르는 값이라 기본값) 안에서 나눕니다 — /out
|
|
1408
|
-
컨텍스트 40,960 · 지금 찬 양 2,087
|
|
1409
|
-
```
|
|
1410
|
-
|
|
1411
|
-
That second-to-last line exists for a reason: **when all three caps are equal, it is the
|
|
1412
|
-
only thing that says whether that is correct.** A low known cap makes them equal, and that
|
|
1413
|
-
is fine. For a while all three read `16,384` always — which meant the table said nothing.
|
|
1414
|
-
|
|
1415
|
-
<details>
|
|
1416
|
-
<summary><b>More</b> — Context length is read off the model · /out · Truncated tool calls</summary>
|
|
1417
|
-
|
|
1418
|
-
### Context length is read off the model
|
|
1419
|
-
|
|
1420
|
-
This one number sizes the whole program: how many files fit in one read, when the
|
|
1421
|
-
conversation gets folded, how long a single reply may be — **all of it comes from here.**
|
|
1422
|
-
|
|
1423
|
-
So deel asks the server on every launch rather than trusting the saved value. The same
|
|
1424
|
-
model name can be loaded at a different length each time, and if that difference never
|
|
1425
|
-
reaches the screen there is no way to notice. **It just quietly gets smaller.**
|
|
1426
|
-
|
|
1427
|
-
```
|
|
1428
|
-
│ Model qwen3-coder (640k tokens) │
|
|
1429
|
-
╰─────────────────────────────────────────────────────────╯
|
|
1430
|
-
✓ Context adjusted 32,768 → 655,360 (read from LM Studio)
|
|
1431
|
-
```
|
|
1432
|
-
|
|
1433
|
-
Every server puts this number under a different name in a different place, so deel checks
|
|
1434
|
-
all of them.
|
|
1435
|
-
|
|
1436
|
-
| Server | Where it reads |
|
|
1437
|
-
|---|---|
|
|
1438
|
-
| LM Studio | `/api/v0/models` — `max_context_length`, `loaded_context_length` |
|
|
1439
|
-
| llama.cpp | `/props` — `n_ctx` |
|
|
1440
|
-
| vLLM | `/v1/models` — `max_model_len` |
|
|
1441
|
-
| Ollama | `/api/show` — `<model>.context_length` |
|
|
1442
|
-
| Other OpenAI-compatible | `/v1/models/<model>` — `context_window`, `context_length`, `max_input_tokens`, `max_position_embeddings` (found even when nested) |
|
|
1443
|
-
|
|
1444
|
-
**Model maximum and loaded length are not the same thing.** LM Studio will happily load a
|
|
1445
|
-
655,360-capable model at 8,192. Trusting the maximum there gets your requests rejected. So
|
|
1446
|
-
the **loaded length is what deel uses**, and the maximum is reported separately.
|
|
1447
|
-
|
|
1448
|
-
```
|
|
1449
|
-
⚠ This model goes up to 655,360 — raise it on the server, then /ctx auto
|
|
1450
|
-
```
|
|
1451
|
-
|
|
1452
|
-
| Command | What it does |
|
|
1453
|
-
|---|---|
|
|
1454
|
-
| `/ctx` | Current length and remaining room |
|
|
1455
|
-
| `/ctx auto` | Ask the server again and match the model |
|
|
1456
|
-
| `/ctx 655360` | Set it yourself (`640k`, `128k`, `1m` also work) |
|
|
1457
|
-
| `/ctx 자세히` | Which endpoints were probed and what each returned — how to see why a lookup failed |
|
|
1458
|
-
| `deel --ctx 655360` | Start at this value (skips the lookup) |
|
|
1459
|
-
|
|
1460
|
-
**`k` means 1024 here.** Context lengths are all powers of two, so that is the only base
|
|
1461
|
-
that lines up: 655,360 is `640k`, not `655k`; 131,072 is `128k`, not `131k`. The display and
|
|
1462
|
-
`/ctx` use the same unit, so typing back what you see gives you the same number.
|
|
1463
|
-
|
|
1464
|
-
### Reply length cap — `/out`
|
|
1465
|
-
|
|
1466
|
-
Context (how much can be held) and the **output cap** (how much can come back at once) are
|
|
1467
|
-
different numbers. Treating them as one makes it impossible to understand why a large file
|
|
1468
|
-
never gets written — the context is roomy while the reply is being cut.
|
|
1469
|
-
|
|
1470
|
-
| Command | What it does |
|
|
1471
|
-
|---|---|
|
|
1472
|
-
| `/out` | Current cap and **where it came from** (set by you / discovered / default) |
|
|
1473
|
-
| `/out 32k` | Set it yourself (`k` is 1024). Saved to the profile |
|
|
1474
|
-
| `/out auto` | Drop your value and go back to the discovered one, or the default |
|
|
1475
|
-
| `deel --max-tokens 65536` | Start at this value |
|
|
1476
|
-
|
|
1477
|
-
The old name `/ctx out 32k` still works.
|
|
1478
|
-
|
|
1479
|
-
**Caps are not fixed numbers.** They are computed from the model's context window and how
|
|
1480
|
-
much of it is currently used — the profile decides what share of the remaining room a stage gets.
|
|
1481
|
-
|
|
1482
|
-
| Model | First call | Continuing | Stuck | Retry after truncation |
|
|
1483
|
-
|---|---|---|---|---|
|
|
1484
|
-
| 2k local | 819 | 716 | 921 | 1,638 |
|
|
1485
|
-
| 8k local | 3,276 | 2,867 | 3,686 | 6,553 |
|
|
1486
|
-
| 40k (qwen3) | 16,384 | 14,336 | 16,384 | 16,384 |
|
|
1487
|
-
| 128k gateway | 16,384 | 16,384 | 16,384 | 16,384 |
|
|
1488
|
-
| 128k, 80% full | 10,485 | 9,174 | 11,796 | 16,384 |
|
|
1489
|
-
| 640k with `/out 65536` | 65,536 | 65,536 | 65,536 | 65,536 |
|
|
1490
|
-
|
|
1491
|
-
Caps shrink as the context fills. Handing a 4k model a 4,096-token cap would leave no room for input.
|
|
1492
|
-
|
|
1493
|
-
The last row is the point: **a known cap overrides the 16,384 default.** For a while it did
|
|
1494
|
-
not — the third argument of `Math.min(cap, max ?? 16384, 16384)` clamped it right back, so a
|
|
1495
|
-
configured cap could only be lowered, never raised. Meanwhile the comment, the README, and the
|
|
1496
|
-
on-screen help all said it could be raised. A documented escape hatch that is welded shut is
|
|
1497
|
-
the worst kind.
|
|
1498
|
-
|
|
1499
|
-
If a cap truncates a reply, **the call is retried with the cap lifted** — and the thinking
|
|
1500
|
-
level drops one notch, because reasoning tokens eat the same budget first. Without that, more
|
|
1501
|
-
headroom just buys more thinking. A truncated reply means a half-written tool call, which fails silently.
|
|
1502
|
-
|
|
1503
|
-
**When the server refuses, it is read for the answer.**
|
|
1504
|
-
|
|
1505
|
-
```
|
|
1506
|
-
This model's maximum context length is 8192 tokens, however you requested 41003
|
|
1507
|
-
```
|
|
1508
|
-
|
|
1509
|
-
The number is extracted, applied, and the call is retried. You never see the failure.
|
|
1510
|
-
No spec knowledge is needed, so **this works against servers we have never seen.**
|
|
1511
|
-
|
|
1512
|
-
### Truncated tool calls
|
|
1513
|
-
|
|
1514
|
-
This actually happened. A user asked for a dashboard; the model tried to put an entire HTML
|
|
1515
|
-
document into `Write`'s arguments, hit the output token limit, and the arguments JSON arrived
|
|
1516
|
-
cut off mid-string.
|
|
1517
|
-
|
|
1518
|
-
The old code quietly turned that unparseable JSON into `{_raw: "..."}` and handed it to the
|
|
1519
|
-
tool. The tool answered `path is empty` — **a message with nothing to do with the real cause.**
|
|
1520
|
-
The model had not omitted the path, so there was nothing to fix; it retried identically, and
|
|
1521
|
-
was truncated again.
|
|
1522
|
-
|
|
1523
|
-
```
|
|
1524
|
-
◆ Write(dashboard.html)
|
|
1525
|
-
└ path is empty ← nine identical times
|
|
1526
|
-
|
|
1527
|
-
── 71s · 13 tool calls · context filled and auto-compacted · no file produced
|
|
1528
|
-
```
|
|
1529
|
-
|
|
1530
|
-
One silently swallowed value produced all of that. What happens now:
|
|
1531
|
-
|
|
1532
|
-
| | Now |
|
|
1533
|
-
|---|---|
|
|
1534
|
-
| Unparseable arguments | **Marked as truncated**, not swallowed. Never passed to the tool |
|
|
1535
|
-
| The model is told | Exactly what happened, and to stop resending the whole thing — write a short skeleton first, then **build it up with `Edit`** |
|
|
1536
|
-
| The truncated payload | Never re-injected into the conversation — it is half a payload and it costs context |
|
|
1537
|
-
| Detecting truncation | Even when the gateway reports `finish_reason: "stop"`, **broken arguments are themselves proof it was cut.** No model writes half a JSON object on purpose |
|
|
1538
|
-
| Three identical failures | The turn stops, with a suggestion to split the request |
|
|
1539
|
-
|
|
1540
|
-
```
|
|
1541
|
-
⊘ Stopped — it is spinning in the same place.
|
|
1542
|
-
the same tool call keeps getting truncated
|
|
1543
|
-
What you asked for in one go is larger than the model's output cap. Try splitting it —
|
|
1544
|
-
e.g. "just the skeleton first" → "now add the table" → "now add the chart"
|
|
1545
|
-
```
|
|
1546
|
-
|
|
1547
|
-
**A step limit (`maxSteps`) cannot catch this.** It cannot tell a long healthy task from a
|
|
1548
|
-
spinning one. What is counted here is not steps but **how many times the same tool failed for
|
|
1549
|
-
the same reason.**
|
|
1550
|
-
|
|
1551
|
-
</details>
|
|
577
|
+
> **More** — Context length is read off the model · /out · Truncated tool calls
|
|
578
|
+
>
|
|
579
|
+
> **[Speed and spend read →](docs/en/tuning.md#reasoning-effort)**
|
|
1552
580
|
|
|
1553
581
|
---
|
|
1554
582
|
|
|
@@ -1617,29 +645,90 @@ The model sees it as `mcp__wiki__search`. `/mcp` shows what is attached.
|
|
|
1617
645
|
**Dependencies stay at zero.** The stdio transport is nothing but newline-delimited JSON-RPC
|
|
1618
646
|
2.0 over a child process's stdin/stdout, so `child_process` and `JSON` cover it. No SDK.
|
|
1619
647
|
|
|
1620
|
-
|
|
1621
|
-
|
|
648
|
+
> **More** — But this is somebody else's program
|
|
649
|
+
>
|
|
650
|
+
> **[Extending read →](docs/en/extend.md#attaching-tools-from-outside-mcp)**
|
|
1622
651
|
|
|
1623
|
-
|
|
652
|
+
---
|
|
1624
653
|
|
|
1625
|
-
|
|
1626
|
-
tear down that line with our own hands. So:
|
|
654
|
+
## Inside your editor (ACP)
|
|
1627
655
|
|
|
1628
|
-
|
|
656
|
+
A tool that makes you open one more terminal window stops being used after about two weeks.
|
|
657
|
+
Developers live inside the IDE. So deel speaks **ACP** (Agent Client Protocol) — Zed,
|
|
658
|
+
JetBrains, Neovim and Emacs attach to it **without changing a line on their side**.
|
|
659
|
+
|
|
660
|
+
One command in your editor's settings:
|
|
661
|
+
|
|
662
|
+
```
|
|
663
|
+
deel acp
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
The editor spawns that as a child process and exchanges newline-delimited JSON-RPC 2.0 over
|
|
667
|
+
stdio. It is not a command you type yourself.
|
|
668
|
+
|
|
669
|
+
**What you get once it is attached:**
|
|
670
|
+
|
|
671
|
+
| In the editor | From deel |
|
|
1629
672
|
|---|---|
|
|
1630
|
-
|
|
|
1631
|
-
|
|
|
1632
|
-
|
|
|
1633
|
-
|
|
|
1634
|
-
|
|
|
1635
|
-
|
|
|
1636
|
-
| **24 tools per server** | Schemas ship on every request. Past that they are dropped, and **the drop is reported** |
|
|
673
|
+
| Streaming reply pane | The model's text and its reasoning |
|
|
674
|
+
| Tool list with icons and status | `Read` is a read, `Edit` is an edit, `Bash` is an execution — **the kind is sent**, not just a name |
|
|
675
|
+
| Clickable file links | The **absolute path** of every file touched |
|
|
676
|
+
| Approval dialog | deel's safety rails, rendered as the editor's own prompt (`allow once` · `always allow` · `reject`) |
|
|
677
|
+
| Mode picker | deel's seven work modes (auto · code · plan · architect · debug · ask · orchestrator) |
|
|
678
|
+
| Stop button | Reaches the turn mid-flight, even while waiting on the model |
|
|
1637
679
|
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
missing?" unanswerable.
|
|
680
|
+
**Still zero dependencies.** Same reason as MCP — newline-delimited JSON-RPC 2.0 is the whole
|
|
681
|
+
transport, so no SDK is needed.
|
|
1641
682
|
|
|
1642
|
-
|
|
683
|
+
> **More** — Details — the places this breaks silently
|
|
684
|
+
>
|
|
685
|
+
> **[Extending read →](docs/en/extend.md#inside-your-editor-acp)**
|
|
686
|
+
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
## Keeping secrets out of the conversation
|
|
690
|
+
|
|
691
|
+
People rarely paste a key. The leak is almost always **command output**.
|
|
692
|
+
|
|
693
|
+
```
|
|
694
|
+
env OPENAI_API_KEY=sk-proj-…
|
|
695
|
+
git remote -v https://user:token@github.com/…
|
|
696
|
+
curl -v > Authorization: Bearer eyJ…
|
|
697
|
+
a failing test log the whole connection string
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
That text goes to the model **and** gets written to `.deel/sessions/*.jsonl` on disk. That
|
|
701
|
+
file is later re-read by `/recall` and can end up inside a `deel pack` bundle. Leak once and
|
|
702
|
+
you have several copies.
|
|
703
|
+
|
|
704
|
+
So it is masked at the single point where tool output enters the conversation.
|
|
705
|
+
|
|
706
|
+
```
|
|
707
|
+
⏺ Bash(env | grep API) done
|
|
708
|
+
⊘ 2 secret-looking values entered the conversation (openai · env var) — masked before the model
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
What it looks for: private-key blocks · OpenAI/Anthropic keys · GitHub tokens · Slack tokens ·
|
|
712
|
+
AWS keys · Google keys · JWTs · credentials embedded in URLs · `Authorization`-family headers ·
|
|
713
|
+
env vars named `…KEY` / `…TOKEN` / `…SECRET` / `…PASSWORD`. Plus **the configured gateway key
|
|
714
|
+
regardless of its shape** — that one is not a guess, it is a known value.
|
|
715
|
+
|
|
716
|
+
### File contents are deliberately not masked
|
|
717
|
+
|
|
718
|
+
`.env` is exactly where masking feels most tempting, and exactly where it backfires: the model
|
|
719
|
+
sees the masked text, edits it, writes it back — and `«가림»` lands where the real key was.
|
|
720
|
+
**Protecting the secret would destroy it.**
|
|
721
|
+
|
|
722
|
+
So on the file side it reports instead of rewriting.
|
|
723
|
+
|
|
724
|
+
```
|
|
725
|
+
⏺ Read(.env) 12 lines
|
|
726
|
+
! 3 secret-looking values entered the conversation (env var)
|
|
727
|
+
— file contents are not masked (masking them would erase the key on write-back)
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
Saying plainly what cannot be stopped beats claiming it was stopped while corrupting the file.
|
|
731
|
+
Either way it lands in the audit log.
|
|
1643
732
|
|
|
1644
733
|
---
|
|
1645
734
|
|
|
@@ -1670,78 +759,9 @@ Undo history stores whole file contents, so repeated edits to large files add up
|
|
|
1670
759
|
it keeps the **most recent 50 turns** and drops the rest. What you just did is always
|
|
1671
760
|
undoable; `/status` shows how large the history currently is.
|
|
1672
761
|
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
### Files removed through `Bash` come back too
|
|
1677
|
-
|
|
1678
|
-
The safety net covered `Write` and `Edit` only. But a model moving a file reaches for
|
|
1679
|
-
`Bash` — `mv old.js new.js`, `rm temp.txt`. The file was gone and `/undo` could do
|
|
1680
|
-
nothing about it. It was half a safety net.
|
|
1681
|
-
|
|
1682
|
-
Now a mutating command snapshots the files it names beforehand, and **says what it saved,
|
|
1683
|
-
right there**.
|
|
1684
|
-
|
|
1685
|
-
```
|
|
1686
|
-
▶ Bash(mv src/old.js src/new.js)
|
|
1687
|
-
└ 성공
|
|
1688
|
-
↩ src/old.js 는 떠 뒀습니다 — /undo 로 되돌아갑니다
|
|
1689
|
-
(saved src/old.js — /undo restores it)
|
|
1690
|
-
```
|
|
1691
|
-
|
|
1692
|
-
`mv` and `rm` leave one "success" line on screen. From that line alone there is no way to
|
|
1693
|
-
tell whether it is reversible, so people either assume it is and move on, or assume it is
|
|
1694
|
-
not and get scared. So the fact is stated.
|
|
1695
|
-
|
|
1696
|
-
**What cannot be saved is not hidden.** Shell-expanded wildcards (`rm *.tmp`), deletions
|
|
1697
|
-
inside a script, and whole directories are invisible here. In those cases the `↩` line
|
|
1698
|
-
simply does not appear — **it never claims "everything is reversible"**. False reassurance
|
|
1699
|
-
means people stop checking.
|
|
1700
|
-
|
|
1701
|
-
Snapshotting casts a **wider** net than blocking does. The scope guard (`checkPaths`) only
|
|
1702
|
-
treats words containing a slash as paths — anything else would block legitimate commands —
|
|
1703
|
-
but `del target.txt`, with no slash, is the most common form there is. This is a reading
|
|
1704
|
-
site rather than a blocking one, so it scans broadly and saves a file only when one is
|
|
1705
|
-
actually there. A wrong guess costs nothing. Up to 24 per command.
|
|
1706
|
-
|
|
1707
|
-
### What it will not read
|
|
1708
|
-
|
|
1709
|
-
Walking a folder turns up things that are not project files: the private stores other coding
|
|
1710
|
-
tools keep — past conversations, command history, caches, and keys. They have nothing to do
|
|
1711
|
-
with the task, but once they appear in a listing the model reads them first.
|
|
1712
|
-
|
|
1713
|
-
```
|
|
1714
|
-
◧ Read(~/.deel/audit.jsonl) 77 lines
|
|
1715
|
-
◧ Read(~/.claude/history.jsonl) 35 lines
|
|
1716
|
-
```
|
|
1717
|
-
|
|
1718
|
-
The audit log is **this program's own record of what it just did.** Reading it back into the
|
|
1719
|
-
conversation makes the model chase its own shadow. It has nothing to do with what was asked,
|
|
1720
|
-
and it fills the context.
|
|
1721
|
-
|
|
1722
|
-
The config file is worse. `.deel/config.json` holds the gateway **API key.** Reading it puts
|
|
1723
|
-
that key into the conversation, sends it to the model, and writes it into the on-disk session
|
|
1724
|
-
log. It hands the key to the very service the key is for.
|
|
1725
|
-
|
|
1726
|
-
| Refused | Why |
|
|
1727
|
-
|---|---|
|
|
1728
|
-
| `.deel/config.json` | Contains the gateway key |
|
|
1729
|
-
| `.deel/audit.jsonl` · `.deel/sessions` · `.deel/history` | deel's own records — chasing its own shadow |
|
|
1730
|
-
| `.claude` `.codex` `.cursor` `.gemini` `.aider` `.continue` `.cline` `.roo` `.kilocode` `.windsurf` `.opencode` `.zed` `.trae` `.augment` `.qodo` `.tabnine` `.cody` `.sourcegraph` `.copilot` `.amazonq` `.junie` `.codeium` `.goose` `.crush` `.gptme` `.openhands` `.devin` | Other tools' private stores |
|
|
1731
|
-
| File-style leftovers like `.aider.chat.history.md` | Same reason |
|
|
1732
|
-
|
|
1733
|
-
Writing is blocked too, not just reading. Blocking only reads would still let the agent
|
|
1734
|
-
overwrite another tool's settings, and overwriting `.deel/config.json` destroys the connection.
|
|
1735
|
-
|
|
1736
|
-
**It blocks, it does not hide** — the refusal says exactly why. New tools keep appearing;
|
|
1737
|
-
when a name is missing from the list, **adding it is one line.**
|
|
1738
|
-
|
|
1739
|
-
That list lives in **exactly one place in the source.** The directory walker (`SKIP_DIRS`) and
|
|
1740
|
-
the read guard look at the same set. They used to be two copies, and two copies means the day
|
|
1741
|
-
comes when only one of them learns a new name — a folder that is skipped while walking but
|
|
1742
|
-
readable if you name it directly, which is very hard to explain.
|
|
1743
|
-
|
|
1744
|
-
</details>
|
|
762
|
+
> **More** — Files removed through Bash come back too · What it will not read
|
|
763
|
+
>
|
|
764
|
+
> **[Safety and corporate review read →](docs/en/safety.md#safety)**
|
|
1745
765
|
|
|
1746
766
|
---
|
|
1747
767
|
|
|
@@ -1753,51 +773,40 @@ deel pack --out deel-import.zip
|
|
|
1753
773
|
|
|
1754
774
|
```
|
|
1755
775
|
✓ deel-import.zip
|
|
1756
|
-
|
|
776
|
+
94 files · 509.6KB
|
|
1757
777
|
|
|
1758
778
|
Dependencies 0
|
|
1759
779
|
Install scripts none
|
|
1760
780
|
External imports 0
|
|
1761
781
|
Network calls 3 sites (configured address only)
|
|
1762
|
-
Ports opened
|
|
782
|
+
Ports opened 1 site (/preview only)
|
|
1763
783
|
```
|
|
1764
784
|
|
|
1765
|
-
The
|
|
1766
|
-
|
|
1767
|
-
-
|
|
1768
|
-
- Presence of `preinstall` / `install` / `postinstall` / `prepare`
|
|
1769
|
-
- **Every network and process-spawn call site found by scanning the source** (file:line)
|
|
1770
|
-
- The three outbound lanes, explained
|
|
1771
|
-
- SHA-256 per file (verify with `certutil -hashfile`)
|
|
1772
|
-
|
|
1773
|
-
It is generated by scanning the source, not written by hand — hand-written sheets drift from reality.
|
|
1774
|
-
Use `deel audit` to read it without building a zip.
|
|
785
|
+
The zip carries **one document for people and two for machines.** A corporate review is
|
|
786
|
+
not a human-only process — security feeds an SBOM to a scanner, and operations reads the
|
|
787
|
+
audit-log spec to write SIEM ingestion rules.
|
|
1775
788
|
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
789
|
+
| File | What |
|
|
790
|
+
|---|---|
|
|
791
|
+
| `반입심사서.txt` | Dependencies · install scripts · **every network and process-spawn call site found by scanning the source** (file:line) · the three outbound lanes · SHA-256 per file |
|
|
792
|
+
| `sbom.cdx.json` | **SBOM (CycloneDX 1.5).** Feed it straight to a scanner. One component per file with SHA-256; dependencies stated as an **explicit empty array** — "not declared" and "none" are different claims |
|
|
793
|
+
| `심사명세.json` | Egress list (per lane: when, where, what, how it's stopped, and the source location) · **audit-log spec** (field names and meanings, plus what is never recorded) · file hashes |
|
|
1780
794
|
|
|
1781
795
|
```bash
|
|
1782
|
-
|
|
796
|
+
deel audit # the human-readable sheet only
|
|
797
|
+
deel sbom # the two machine-readable ones, on stdout (deel sbom | jq)
|
|
798
|
+
deel sbom --out review.json # to a file
|
|
799
|
+
deel sbom --only sbom # just the SBOM
|
|
1783
800
|
```
|
|
1784
801
|
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
| Basic chat | Address, key and model name are right |
|
|
1790
|
-
| System message | Rules (`DEEL.md`) and skills take effect |
|
|
1791
|
-
| Streaming | Output can flow token by token |
|
|
1792
|
-
| **Tool calls** | **Whether it can read and edit files — the critical one** |
|
|
1793
|
-
| **Tool results** | **Whether multi-turn works — the premise of the agent loop** |
|
|
1794
|
-
| Structured output | Edit format can be enforced by schema |
|
|
1795
|
-
| Reasoning control | Whether `/think` works at the model layer |
|
|
1796
|
-
| Context length | How many files can be read at once |
|
|
802
|
+
All three are generated by scanning the source, never written by hand — hand-written sheets
|
|
803
|
+
drift, and **a review document that drifts is worse than none.** Find one wrong line and the
|
|
804
|
+
reviewer stops trusting the rest. The audit-log spec is the one hand-written part, so a test
|
|
805
|
+
checks it against real log records on every run.
|
|
1797
806
|
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
807
|
+
> **More** — Diagnosing a corporate gateway
|
|
808
|
+
>
|
|
809
|
+
> **[Safety and corporate review read →](docs/en/safety.md#corporate-review-package)**
|
|
1801
810
|
|
|
1802
811
|
---
|
|
1803
812
|
|
|
@@ -1805,54 +814,9 @@ Verdict is one of **ready · limited · blocked · unreachable**.
|
|
|
1805
814
|
|
|
1806
815
|
Stored in `~/.deel/config.json`. A `.deel/config.json` in the project folder takes precedence.
|
|
1807
816
|
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
### Supported servers
|
|
1812
|
-
|
|
1813
|
-
| | Example address |
|
|
1814
|
-
|---|---|
|
|
1815
|
-
| Corporate AI gateway (OpenAI-compatible) | `https://ai-gw.example.corp/v1` |
|
|
1816
|
-
| Ollama | `http://localhost:11434` |
|
|
1817
|
-
| LM Studio | `http://localhost:1234/v1` |
|
|
1818
|
-
| llama.cpp · vLLM · LiteLLM | `http://host:port/v1` |
|
|
1819
|
-
|
|
1820
|
-
Auth style is detected automatically: `Authorization: Bearer` → `x-api-key` → `api-key` (Azure) → none.
|
|
1821
|
-
|
|
1822
|
-
### Environment variables
|
|
1823
|
-
|
|
1824
|
-
| Variable | Use |
|
|
1825
|
-
|---|---|
|
|
1826
|
-
| `DEEL_API_KEY` | Keep the key out of the config file (takes precedence) |
|
|
1827
|
-
| `DEEL_KEY_<PROFILE_ID>` | Per-profile key |
|
|
1828
|
-
| `NODE_EXTRA_CA_CERTS` | Corporate TLS certificate |
|
|
1829
|
-
| `HTTPS_PROXY` | Behind a proxy |
|
|
1830
|
-
| `DEEL_DEBUG=1` | Verbose errors |
|
|
1831
|
-
| `NO_COLOR` | Disable colour |
|
|
1832
|
-
|
|
1833
|
-
### Flags
|
|
1834
|
-
|
|
1835
|
-
```bash
|
|
1836
|
-
deel --root <folder> Working scope. Defaults to the current folder
|
|
1837
|
-
deel --mode <mode> auto (default) / confirm / strict
|
|
1838
|
-
deel --work <mode> auto (default) / code / plan / architect / debug / ask / orchestrator
|
|
1839
|
-
deel --level <level> 쉬움 (simple) / 개발자 (developer)
|
|
1840
|
-
deel --ctx <length> Set the context length yourself (655360 · 640k · 128k)
|
|
1841
|
-
deel --max-tokens <len> Cap on a single reply (32k) — same value as /out
|
|
1842
|
-
deel --think <level> off / low / medium (default) / high / max
|
|
1843
|
-
deel --effort <profile> even / save (default) / deep
|
|
1844
|
-
deel --offline Nothing leaves this machine
|
|
1845
|
-
deel --continue Resume the most recent conversation
|
|
1846
|
-
deel --resume <id> Resume a specific one
|
|
1847
|
-
deel --no-tui Turn the input box off; plain scrolling view (see below)
|
|
1848
|
-
```
|
|
1849
|
-
|
|
1850
|
-
### Project rules
|
|
1851
|
-
|
|
1852
|
-
If the working folder has `DEEL.md`, `CLAUDE.md` or `AGENTS.md`, it is loaded as project rules.
|
|
1853
|
-
`/init` scaffolds one.
|
|
1854
|
-
|
|
1855
|
-
</details>
|
|
817
|
+
> **More** — Supported servers · Environment variables · Flags · Project rules
|
|
818
|
+
>
|
|
819
|
+
> **[Configuration read →](docs/en/config.md#configuration)**
|
|
1856
820
|
|
|
1857
821
|
---
|
|
1858
822
|
|
|
@@ -1919,221 +883,21 @@ so one run tells you everything.
|
|
|
1919
883
|
| `no-bundle` | 12 | Nothing foreign in the published package; test-file hygiene |
|
|
1920
884
|
| `edit-bench` | 20 cases | Edit success rate |
|
|
1921
885
|
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
### Coverage
|
|
1926
|
-
|
|
1927
|
-
```bash
|
|
1928
|
-
npm run coverage Summary
|
|
1929
|
-
node test/coverage.mjs --file src/repl.js One file in detail
|
|
1930
|
-
node test/coverage.mjs --json Machine-readable
|
|
1931
|
-
```
|
|
1932
|
-
|
|
1933
|
-
Zero dependencies rules out c8 and nyc, so this reads Node's own
|
|
1934
|
-
`NODE_V8_COVERAGE` instead — nothing new to get through an import review. It picks up
|
|
1935
|
-
child processes too, so the `cli` suite that spawns `deel` counts like everything else.
|
|
1936
|
-
|
|
1937
|
-
Currently **92% overall** (7,056 of 7,646 lines). Three files are deliberately left short.
|
|
1938
|
-
|
|
1939
|
-
| File | Now | Why it stops there |
|
|
1940
|
-
|---|---|---|
|
|
1941
|
-
| `tools/excel.js` | 67% | The password path needs Excel installed and a genuinely encrypted file. Faking it would produce a test that only *looks* like it passes |
|
|
1942
|
-
| `repl.js` | 77% | The keypress paths — Shift+Tab, Ctrl+C, password entry, paste. Reaching them needs a pty, and a pty is a dependency. What the screen *prints* is measured instead, as a value (`ui` and `tui` suites) |
|
|
1943
|
-
| `plugins/manage.js` | 79% | The GitHub download path. **Tests not reaching the network** matters more. Folder installs are covered |
|
|
1944
|
-
|
|
1945
|
-
### Layout
|
|
1946
|
-
|
|
1947
|
-
```
|
|
1948
|
-
bin/deel.js entry point
|
|
1949
|
-
src/
|
|
1950
|
-
repl.js the conversation screen — what a person faces
|
|
1951
|
-
oneshot.js run once and exit (-p)
|
|
1952
|
-
commands.js 35 slash commands
|
|
1953
|
-
setup.js first-run connection setup
|
|
1954
|
-
config.js reading and writing config
|
|
1955
|
-
|
|
1956
|
-
ui/ansi.js colour · East Asian width
|
|
1957
|
-
ui/screen.js picking a screen (line mode / box mode)
|
|
1958
|
-
ui/inputbox.js the box at the bottom — overwrite-in-place, cursor position
|
|
1959
|
-
ui/status.js status line — model, context, mode, approvals
|
|
1960
|
-
ui/working.js working phrases — they follow what is happening
|
|
1961
|
-
ui/motion.js the braille drawing next to the phrase
|
|
1962
|
-
ui/approve.js approval mode display (auto / risky only / everything)
|
|
1963
|
-
ui/diff.js showing what changed, where it changed
|
|
1964
|
-
ui/wrap.js wrapping to width without breaking colour
|
|
1965
|
-
ui/level.js simple vs developer
|
|
1966
|
-
|
|
1967
|
-
agent/loop.js the agent loop
|
|
1968
|
-
agent/session.js conversation state + context accounting
|
|
1969
|
-
agent/modes.js work modes (auto · code · plan · architect · debug · ask · orchestrator)
|
|
1970
|
-
agent/route.js picking the mode from what was said
|
|
1971
|
-
agent/effort.js per-stage reasoning effort
|
|
1972
|
-
agent/budget.js shares that follow the window — lines read, description length, steps
|
|
1973
|
-
agent/project.js working out what kind of project this folder is
|
|
1974
|
-
agent/compact.js summarising compaction
|
|
1975
|
-
agent/store.js saving and resuming conversations
|
|
1976
|
-
agent/recall.js searching past conversations (no index, within budget)
|
|
1977
|
-
agent/memory.js what outlives the conversation
|
|
1978
|
-
agent/mention.js attaching files with `@`
|
|
1979
|
-
|
|
1980
|
-
backend/http.js the single HTTP layer (the only door out)
|
|
1981
|
-
backend/detect.js protocol and auth detection
|
|
1982
|
-
backend/adapter.js absorbing OpenAI/Ollama differences + streaming parser
|
|
1983
|
-
backend/ctxsize.js reading context length off the model
|
|
1984
|
-
backend/probe.js 8 diagnostic checks
|
|
1985
|
-
backend/scan.js scanning for local servers
|
|
1986
|
-
backend/mcp.js attaching outside tools (MCP, stdio)
|
|
1987
|
-
|
|
1988
|
-
tools/index.js 15 tools
|
|
1989
|
-
tools/edit-match.js staged-relaxation edit matching
|
|
1990
|
-
tools/outline.js a file's shape, cheaply
|
|
1991
|
-
tools/verify.js checking what was built
|
|
1992
|
-
tools/task.js splitting big work off
|
|
1993
|
-
tools/jobs.js commands that run in the background
|
|
1994
|
-
tools/todo.js checklists
|
|
1995
|
-
tools/webfetch.js reading the web (read-only)
|
|
1996
|
-
tools/encoding.js writing back in the encoding it was read in
|
|
1997
|
-
tools/xlsx.js Excel → CSV (written here)
|
|
1998
|
-
|
|
1999
|
-
preview/serve.js serving what you built (127.0.0.1 only)
|
|
2000
|
-
skills/discover.js finding skills, commands and plugins on the machine
|
|
2001
|
-
plugins/manage.js installing, removing and packing plugins
|
|
2002
|
-
pack/zip.js ZIP writing (written here, keeps non-ASCII names)
|
|
2003
|
-
pack/tar.js TAR reading (written here)
|
|
2004
|
-
pack/selfpack.js review dossier + source bundle
|
|
2005
|
-
|
|
2006
|
-
safety/network.js the lock on the way out
|
|
2007
|
-
safety/guard.js working scope + dangerous-command blocking
|
|
2008
|
-
safety/undo.js snapshots and undo
|
|
2009
|
-
safety/audit.js recording what happened, and when
|
|
2010
|
-
test/ tests (excluded from the published package)
|
|
2011
|
-
```
|
|
2012
|
-
|
|
2013
|
-
</details>
|
|
886
|
+
> **More** — Coverage · Layout
|
|
887
|
+
>
|
|
888
|
+
> **[Development read →](docs/en/develop.md#development)**
|
|
2014
889
|
|
|
2015
890
|
---
|
|
2016
891
|
|
|
2017
892
|
## Release notes
|
|
2018
893
|
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
| | Before | After |
|
|
2025
|
-
|---|---|---|
|
|
2026
|
-
| Resuming | a conversation cut mid-tool-call **would not reopen** | unmatched calls are cleared, then it opens |
|
|
2027
|
-
| Counting tokens | it guessed, and stayed wrong | it corrects itself against the server |
|
|
2028
|
-
| Making room | summarising arrived at turn 49 | it holds out to turn **102** |
|
|
2029
|
-
| Side questions | piled up in the main context | live in their own thread |
|
|
2030
|
-
| Yesterday's lesson | vanished when you quit | carries over to the next session |
|
|
2031
|
-
| The answer on screen | `**bold**` showed up as characters | it is drawn |
|
|
2032
|
-
|
|
2033
|
-
<br>
|
|
2034
|
-
|
|
2035
|
-
#### 1. A conversation cut mid-tool-call would not reopen
|
|
2036
|
-
|
|
2037
|
-
Close the window or hit <kbd>Ctrl</kbd>+<kbd>C</kbd> while a tool is running and the saved conversation keeps **a call with no result under it**. Reopen it with `--resume` and the server rejects the mismatch with a 400 — the conversation was written down perfectly well, and you still could not carry on.
|
|
2038
|
-
|
|
2039
|
-
Now the pairs are checked before it opens. Calls with no result go, results with no parent go, and **whatever the model said stays.**
|
|
2040
|
-
|
|
2041
|
-
```
|
|
2042
|
-
$ deel --resume 20260826-140217
|
|
2043
|
-
|
|
2044
|
-
✓ 20260826-140217 — 메시지 48개를 이어 받았습니다.
|
|
2045
|
-
중단된 도구 호출 2개를 걷어냈습니다 — 그때 하던 일은 다시 시켜 주세요.
|
|
2046
|
-
```
|
|
2047
|
-
|
|
2048
|
-
#### 2. It misjudged the room left
|
|
2049
|
-
|
|
2050
|
-
Token counts are estimated from character counts. Mix Korean, code and JSON and that estimate drifts from the truth — so deel folded early with room to spare, or did not fold when there was none and the server refused.
|
|
2051
|
-
|
|
2052
|
-
It now **corrects the multiplier against what the server actually reports** with every answer. One line at the foot of `/context`:
|
|
2053
|
-
|
|
2054
|
-
```
|
|
2055
|
-
서버가 알려 준 실제값에 맞춰 +12% 보정했습니다 (7번 재봄).
|
|
2056
|
-
```
|
|
2057
|
-
|
|
2058
|
-
The multiplier is kept per model, so **the next session starts from it** instead of measuring again from scratch.
|
|
2059
|
-
|
|
2060
|
-
#### 3. Summarising arrived too early
|
|
2061
|
-
|
|
2062
|
-
At 80% of the window, earlier turns get folded into a summary. That **cannot be undone**, and the file contents the reasoning rested on are gone with it.
|
|
2063
|
-
|
|
2064
|
-
There is now a step before it. At 55%, **only older tool results** are folded — the four most recent are left alone, and nothing the model or you said is touched at all.
|
|
2065
|
-
|
|
2066
|
-
```
|
|
2067
|
-
◲ 오래된 도구 결과 6개를 접었습니다 (2,148 토큰을 비움)
|
|
2068
|
-
```
|
|
2069
|
-
|
|
2070
|
-
What was there is left in its place:
|
|
2071
|
-
|
|
2072
|
-
```
|
|
2073
|
-
(접힘) Read(src/runner.js) — 61줄. 자리를 비우려고 내용을 접었습니다. 필요하면 다시 읽으세요.
|
|
2074
|
-
```
|
|
2075
|
-
|
|
2076
|
-
Measured by streaming the same conversation through: summarising is pushed from **turn 49 to turn 102 — 2.1×**.
|
|
2077
|
-
|
|
2078
|
-
#### 4. Side questions polluted the main line
|
|
2079
|
-
|
|
2080
|
-
"Just check this one thing" piles into the main context and stays there long after the checking is done.
|
|
2081
|
-
|
|
2082
|
-
```
|
|
2083
|
-
/thread new 로그확인
|
|
2084
|
-
⑂ 로그확인 갈래로 왔습니다. 빈 대화입니다
|
|
2085
|
-
본줄기로 돌아가려면 /thread 1
|
|
2086
|
-
```
|
|
2087
|
-
|
|
2088
|
-
`fork` carries the conversation so far with you. What threads **keep apart is the messages, the token count and the checklist**; what they **share is the connection, undo and the audit log** — a file changed inside a thread still comes back with `/undo`. The `⑂` marker appears in the status line only once there is more than one thread.
|
|
2089
|
-
|
|
2090
|
-
#### 5. Yesterday's lesson vanished when you quit
|
|
2091
|
-
|
|
2092
|
-
deel could work out that `pnpm` is not on this machine, and lose it the moment you quit. Tomorrow it calls it again, fails again, works around it again.
|
|
2093
|
-
|
|
2094
|
-
```
|
|
2095
|
-
/learned
|
|
2096
|
-
── 겪어 본 것 ──────────────────────────────────────
|
|
2097
|
-
|
|
2098
|
-
이 폴더에서 돌려 본 명령
|
|
2099
|
-
✓ npm test 됨 12 · 안 됨 0
|
|
2100
|
-
✗ pnpm 됨 0 · 안 됨 3
|
|
2101
|
-
|
|
2102
|
-
이 모델에 대해 qwen2.5-coder:7b
|
|
2103
|
-
같이 걸어 본 걸음 86
|
|
2104
|
-
인자가 잘림 14 (16%)
|
|
2105
|
-
토큰 추정 보정 ×1.12
|
|
2106
|
-
|
|
2107
|
-
이 중 프롬프트에 실리는 것
|
|
2108
|
-
- 여기서 되는 명령: `npm test`
|
|
2109
|
-
- 이 PC 에서 안 되는 명령(다시 부르지 마라): `pnpm`
|
|
2110
|
-
```
|
|
2111
|
-
|
|
2112
|
-
**This is not training.** It does not touch the model and it does not hoard conversations — that would only eat context. It counts, and it carries over **only what it has seen twice**, all of it **within 220 tokens**. Something seen once may be a coincidence, and writing a coincidence down as fact sends the model around a road that actually works.
|
|
2113
|
-
|
|
2114
|
-
Commands that work live with the folder (`.deel/배운것.json`); the model's habits live in the config folder. So **move the folder and what it learned about the model comes along.** `/learned 지우기` empties it whenever you want.
|
|
2115
|
-
|
|
2116
|
-
#### 6. The answer showed up as raw characters
|
|
2117
|
-
|
|
2118
|
-
The model speaks Markdown and the screen did not know it, so asterisks, backticks and hashes came through mixed into the prose. You had to re-read it in your head to see what was a heading and what was code.
|
|
2119
|
-
|
|
2120
|
-
```
|
|
2121
|
-
before after
|
|
2122
|
-
▌ ## 고친 것 ▌ ▍ 고친 것
|
|
2123
|
-
▌ **src/runner.js** 의 `console.log` ▌ src/runner.js 의 console.log
|
|
2124
|
-
▌ - [ ] 남은 것: `src/worker.js` ▌ ☐ 남은 것: src/worker.js
|
|
2125
|
-
▌ ```js ▌ ┌──────────────── js
|
|
2126
|
-
▌ log.info('시작', { id }) ▌ │ log.info('시작', { id })
|
|
2127
|
-
▌ |---|---| ▌ ┼────────┼─────────┼
|
|
2128
|
-
```
|
|
2129
|
-
|
|
2130
|
-
Answers arrive in fragments, so a line can only be drawn **once it ends**. But a whole paragraph on one line would leave the screen still for seconds — so once a line grows past the screen width, everything up to there is **streamed raw**. Looking alive comes before looking neat.
|
|
2131
|
-
|
|
2132
|
-
<br>
|
|
2133
|
-
|
|
2134
|
-
Tests 2,532 → **2,578** · 48/48 files. Earlier releases are in the [tags](https://github.com/jysvai/deel-local-cli/tags).
|
|
894
|
+
| Version | What changed |
|
|
895
|
+
|---|---|
|
|
896
|
+
| **[1.4.0](docs/en/releases.md#140)** | deel gets a face, speaks English, and sees meaning — eleven places |
|
|
897
|
+
| [1.3.0](docs/en/releases.md#130) | Evidence instead of claims, the editor instead of a terminal — six places |
|
|
898
|
+
| [1.2.0](docs/en/releases.md#120) | So the conversation doesn't break — six places |
|
|
2135
899
|
|
|
2136
|
-
|
|
900
|
+
What changed and why is in the **[release notes](docs/en/releases.md)**.
|
|
2137
901
|
|
|
2138
902
|
---
|
|
2139
903
|
|