mini-code-cli 0.1.1.3__tar.gz → 0.1.1.4__tar.gz

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.
Files changed (45) hide show
  1. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/PKG-INFO +62 -12
  2. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/README.md +61 -11
  3. mini_code_cli-0.1.1.4/mini_code_cli/agent_files.py +90 -0
  4. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/agent_loop.py +526 -58
  5. mini_code_cli-0.1.1.4/mini_code_cli/compaction.py +245 -0
  6. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/config.py +35 -19
  7. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/permissions.py +15 -9
  8. mini_code_cli-0.1.1.4/mini_code_cli/planning.py +29 -0
  9. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/prompts.py +144 -6
  10. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/runner.py +7 -1
  11. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/subagents/base.py +64 -8
  12. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/subagents/builtin.py +10 -9
  13. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/tokens.py +66 -0
  14. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/tools.py +92 -30
  15. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/ui.py +151 -5
  16. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/utils.py +92 -53
  17. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli.egg-info/PKG-INFO +62 -12
  18. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli.egg-info/SOURCES.txt +9 -1
  19. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/pyproject.toml +1 -1
  20. mini_code_cli-0.1.1.4/tests/test_advanced_features.py +459 -0
  21. mini_code_cli-0.1.1.4/tests/test_cli_features.py +177 -0
  22. mini_code_cli-0.1.1.4/tests/test_config.py +82 -0
  23. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/tests/test_e2e_agent_loop.py +53 -1
  24. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/tests/test_interactive.py +11 -0
  25. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/tests/test_permissions.py +8 -0
  26. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/tests/test_subagents.py +88 -0
  27. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/tests/test_tokens.py +29 -2
  28. mini_code_cli-0.1.1.4/tests/test_tools.py +151 -0
  29. mini_code_cli-0.1.1.4/tests/test_utils.py +93 -0
  30. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/LICENSE +0 -0
  31. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/__init__.py +0 -0
  32. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/__main__.py +0 -0
  33. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/persistence.py +0 -0
  34. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/plan.py +0 -0
  35. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/sandbox.py +0 -0
  36. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/shell_safety_utils.py +0 -0
  37. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/skills.py +0 -0
  38. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli/subagents/__init__.py +0 -0
  39. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli.egg-info/dependency_links.txt +0 -0
  40. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli.egg-info/entry_points.txt +0 -0
  41. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli.egg-info/requires.txt +0 -0
  42. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/mini_code_cli.egg-info/top_level.txt +0 -0
  43. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/setup.cfg +0 -0
  44. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/tests/test_release_script.py +0 -0
  45. {mini_code_cli-0.1.1.3 → mini_code_cli-0.1.1.4}/tests/test_runner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mini-code-cli
3
- Version: 0.1.1.3
3
+ Version: 0.1.1.4
4
4
  Summary: Mini Coding Agent. Allows you to easily experiment with a small coding agent.
5
5
  Author-email: Nikolai Rozanov <nikolai.rozanov@gmail.com>
6
6
  License-Expression: AGPL-3.0-only
@@ -67,7 +67,7 @@ mini-code --url "https://api.deepseek.com" --model "deepseek-v4-flash"
67
67
  **3 — The shortcuts** (plan mode, sub-agents, shell, auto-mode, no permission prompts):
68
68
 
69
69
  ```bash
70
- mini-code --all # = --plan --enable-subagents --enable-shell --auto-mode --sudo
70
+ mini-code --all # = --plan --enable-subagents --enable-shell --skills --auto-mode --sudo
71
71
  mini-code --all-last # ...and continue your last session
72
72
  ```
73
73
 
@@ -95,20 +95,23 @@ given a reference implementation.
95
95
  | `--prompt TEXT` | — | initial user prompt |
96
96
  | `-a`, `--auto-mode` | off | keep querying the model and running tools until no tool calls remain |
97
97
  | `--agent-md FILE` | — | append an `agent.md` file after the system prompt (e.g. `./skill.md`) |
98
- | `--ask-permission` | off | ask before every tool call (ALLOW-tier shell commands still skip the prompt) |
98
+ | `--ask-permission` | off | ask before **every** tool call, including an ALLOW-tier shell command (`--sudo` disables all prompts) |
99
99
  | `--sudo` | off | **dangerous:** never ask. DENY-tier commands are still refused |
100
100
  | `--allowed-dir DIR` | `./` | sandbox for **file** tools (does not restrict the shell) |
101
101
  | `-s`, `--enable-shell` | off | allow shell execution (classifier always applies) |
102
102
  | `-g`, `--enable-subagents` | off | expose sub-agents as tools |
103
- | `--skills` | off | enable the `.mini` skills directory (`skill.md`s, `SKILLS.md`, runnable scripts) |
104
- | `-p`, `--plan` | off | plan mode (`CURRENT_GOAL.md` / `CURRENT_PLAN.md`, `/plan`) |
103
+ | `--skills` | off | enable the `.mini` skills directory (`skill.md`s, `SKILLS.md`, runnable scripts). **`run_skill` executes those Python scripts — arbitrary code execution, even without `--enable-shell`**; only enable it for a directory you trust |
104
+ | `-p`, `--plan` | off | plan mode (`CURRENT_GOAL.md` / `CURRENT_PLAN.md`, printed plan, `/plan`, `/skip-plan`) |
105
+ | `--plan-strategy NAME` | `plan-verify-step` | `plan-verify-step`, `plan-verify` or `open-plan` (implies `--plan`) |
106
+ | `--scratchpad` | off | give the agent a free-form `.mini/SCRATCHPAD.md` (plus further scratch files) for thoughts, plans and learnings |
107
+ | `--compaction-strategy NAME` | `summarise` | `summarise`, `predict-files` or `predict-messages` |
105
108
  | `--llm-timeout S` | `500` | HTTP timeout for LLM requests |
106
109
  | `--tool-timeout S` | `120` | timeout for a single tool call |
107
110
  | `--max-context-tokens N` | derived | input-token budget before the history is compacted |
108
111
  | `--cache-dir DIR` | `~/.cache/mini/sessions/` | where session histories are stored |
109
112
  | `--restore-session PATH` | — | continue a specific previous session |
110
113
  | `-l`, `--load-last-session` | off | continue the session recorded in the `.mini` pointer |
111
- | `--all` | off | `--plan --enable-subagents --enable-shell --auto-mode --sudo` |
114
+ | `--all` | off | `--plan --enable-subagents --enable-shell --skills --auto-mode --sudo` |
112
115
  | `--all-last` | off | `--all` + `--load-last-session` |
113
116
  | `--verbose` | off | print full detail (default: user/assistant turns, token usage, tool calls only) |
114
117
  | `-h`, `--help` | — | show the built-in help |
@@ -151,8 +154,10 @@ mini-code --enable-subagents # the available sub-agents then show up in /h
151
154
 
152
155
  > [!NOTE]
153
156
  > A sub-agent's `tools`, `enable_shell` and `max_steps` are always **intersected with the
154
- > parent's** permissions, so it can never do anything the main agent could not. Sub-agents
155
- > compose with `--plan`: each keeps its own `CURRENT_PLAN.md` / `CURRENT_GOAL.md`.
157
+ > parent's** permissions, so it can never do anything the main agent could not. The `tools`
158
+ > allowlist is enforced on the nested session itself (both the schemas offered to the model and
159
+ > the dispatch table), not merely described in its prompt. Sub-agents compose with `--plan`:
160
+ > each keeps its own `CURRENT_PLAN.md` / `CURRENT_GOAL.md`.
156
161
 
157
162
  <details>
158
163
  <summary><b>Adding your own sub-agent</b></summary>
@@ -190,9 +195,16 @@ to the model automatically when `--enable-subagents` is set. See
190
195
  | `/reset [<n>]` | rewind to the end of turn `n` (`last` works too); drops everything after it |
191
196
  | `/clear` | clear the screen (keeps the conversation history) |
192
197
  | `/plan` | show the current goal + plan (plan mode only) |
198
+ | `/context` | show how the context window is used: tokens and percentages by category (system prompt, user/assistant messages, tool calls/outputs, reasoning, overhead) |
199
+ | `/skip-plan <prompt>` | send `<prompt>` once without generating or reviewing a plan |
193
200
  | `/help` | show this help |
194
201
  | `/quit`, `/exit` | save the session and exit |
195
202
 
203
+ **Multi-line input:** press `Shift+Enter` (or `Ctrl-J`) to insert a newline; plain
204
+ `Enter` sends the turn. This works in the session prompt and the startup tip
205
+ reminds you. Terminals that report `Shift+Enter` as a CSI-u/modifyOtherKeys
206
+ sequence are recognised; elsewhere `Ctrl-J` inserts the newline.
207
+
196
208
  > [!NOTE]
197
209
  > `/history` and `/reset` are driven by `summary_history.json`, a flat recorder that maps every
198
210
  > turn to the `history_{n}.json` segment and message index it lives in — so no full history is
@@ -251,6 +263,9 @@ command into one of three tiers:
251
263
  | **ASK** | `rm file`, `sudo ...`, `chmod`, `curl ... \| sh` | requires your confirmation |
252
264
  | **ALLOW** | `ls`, `cat`, `git status` | runs without prompting |
253
265
 
266
+ `--sudo` removes the confirmation prompts (ASK tier and `--ask-permission`); DENY commands are
267
+ still refused. With no flags, an ASK-tier command prompts and an ALLOW-tier one runs unaided.
268
+
254
269
  > [!WARNING]
255
270
  > The classifier is **always enforced** — even in auto-mode and with `--sudo` — so the agent
256
271
  > cannot run destructive commands unattended. It is a heuristic, not a sandbox: use it with care.
@@ -261,13 +276,34 @@ command into one of three tiers:
261
276
  The loop keeps two human-readable tracking files in the session directory: `CURRENT_GOAL.md`
262
277
  (your latest instruction) and `CURRENT_PLAN.md` (a step-by-step plan for that goal, marked
263
278
  finished when it is done). They are authored by the *loop*, not the agent, live outside
264
- `--allowed-dir`, and can be inspected any time with `/plan`.
279
+ `--allowed-dir`, and can be inspected any time with `/plan`. The generated plan is
280
+ also printed as a box right after planning, so you can see it without asking.
281
+ Use `/skip-plan <prompt>` to send one prompt without planning it (plan mode stays
282
+ on for later turns).
283
+
284
+ `--plan-strategy` selects how planning is wired:
285
+
286
+ | Strategy | What happens |
287
+ | --- | --- |
288
+ | `plan-verify-step` (default) | Current behaviour: author a plan, review it once the work settles, then run one extra step and keep whatever that step says. |
289
+ | `plan-verify` | Same plan + review, but the post-review step is kept only when it calls a tool. A no-tool answer is shown to you and ends the turn without being appended to the transcript. |
290
+ | `open-plan` | The agent owns a plan document at `.mini/PLAN.md` inside `--allowed-dir`, reads and updates it with the normal file tools, and the loop neither authors nor reviews a plan. |
265
291
 
266
292
  > [!NOTE]
267
293
  > Plan mode also changes **history compaction**: after the transcript is compacted to a summary,
268
294
  > `CURRENT_PLAN.md` and `CURRENT_GOAL.md` are re-injected, so the agent keeps working against the
269
- > same goal. When the work looks done the plan is reviewed and any outstanding task is re-queued
270
- > before the agent returns to you.
295
+ > same goal. With `open-plan`, the agent's `.mini/PLAN.md` is re-injected instead. When the work
296
+ > looks done the plan is reviewed and any outstanding task is re-queued before the agent returns
297
+ > to you (except with `open-plan`).
298
+
299
+ ### Scratchpad — `--scratchpad`
300
+
301
+ With `--scratchpad`, the loop creates `.mini/SCRATCHPAD.md` inside `--allowed-dir` and tells the
302
+ agent that it may read and write that file freely, and may create additional scratch files in the
303
+ same directory (for example `SCRATCH-NOTES.md`, `SCRATCH-IDEAS.md`). The scratchpad is ordinary
304
+ state inside the sandbox, so the normal `read_file` / `write_file` / `edit` tools work; no special
305
+ tool is registered. It is meant for the agent's own thoughts, plans, learnings and open questions,
306
+ and survives a history compaction because it lives on disk.
271
307
 
272
308
  ### Sessions — resume, or start fresh
273
309
 
@@ -315,6 +351,20 @@ waiting on) is kept verbatim after the summary. So a compaction that fires just
315
351
  instruction cannot swallow it — the model still answers what you asked, and the turn stays in
316
352
  the session file, in `/history` and in a later restore.
317
353
 
354
+ `--compaction-strategy` chooses what else survives besides the summary:
355
+
356
+ | Strategy | Messages after compaction |
357
+ | --- | --- |
358
+ | `summarise` (default) | `system`, `summary`, `plan`, `current turn` |
359
+ | `predict-files` | `system`, `summary`, predicted read-only tool calls + results, `plan`, `current turn` |
360
+ | `predict-messages` | `system`, `summary`, original messages the model names by index, `plan`, `current turn` |
361
+
362
+ `predict-files` asks the model which files it needs to re-read and executes only the read-only
363
+ tools (`read_file`, `grep`, `glob`) it predicts; `predict-messages` asks for a JSON array of
364
+ 0-based message indexes to keep verbatim. Both predictions are one extra tool-free (or
365
+ read-only-tool) LLM call, are billed normally, and are capped so they cannot refill the context
366
+ they just freed. A failed prediction degrades to the plain summary.
367
+
318
368
  Because a rollover leaves no trace in the transcript (the old turns really are gone), the
319
369
  console says in plain terms what happened — all of it without `--verbose`:
320
370
 
@@ -379,7 +429,7 @@ If you use `mini-code-cli` in your research or writing, please cite it:
379
429
  author = {Rozanov, Nikolai},
380
430
  title = {mini-code-cli: A minimal, dependency-light coding agent},
381
431
  year = {2026},
382
- version = {0.1.1.2},
432
+ version = {0.1.1.4},
383
433
  howpublished = {\url{https://github.com/ai-nikolai/mini-code-cli}},
384
434
  note = {A no-bloat, dependency-light agent CLI for experimenting.}
385
435
  }
@@ -48,7 +48,7 @@ mini-code --url "https://api.deepseek.com" --model "deepseek-v4-flash"
48
48
  **3 — The shortcuts** (plan mode, sub-agents, shell, auto-mode, no permission prompts):
49
49
 
50
50
  ```bash
51
- mini-code --all # = --plan --enable-subagents --enable-shell --auto-mode --sudo
51
+ mini-code --all # = --plan --enable-subagents --enable-shell --skills --auto-mode --sudo
52
52
  mini-code --all-last # ...and continue your last session
53
53
  ```
54
54
 
@@ -76,20 +76,23 @@ given a reference implementation.
76
76
  | `--prompt TEXT` | — | initial user prompt |
77
77
  | `-a`, `--auto-mode` | off | keep querying the model and running tools until no tool calls remain |
78
78
  | `--agent-md FILE` | — | append an `agent.md` file after the system prompt (e.g. `./skill.md`) |
79
- | `--ask-permission` | off | ask before every tool call (ALLOW-tier shell commands still skip the prompt) |
79
+ | `--ask-permission` | off | ask before **every** tool call, including an ALLOW-tier shell command (`--sudo` disables all prompts) |
80
80
  | `--sudo` | off | **dangerous:** never ask. DENY-tier commands are still refused |
81
81
  | `--allowed-dir DIR` | `./` | sandbox for **file** tools (does not restrict the shell) |
82
82
  | `-s`, `--enable-shell` | off | allow shell execution (classifier always applies) |
83
83
  | `-g`, `--enable-subagents` | off | expose sub-agents as tools |
84
- | `--skills` | off | enable the `.mini` skills directory (`skill.md`s, `SKILLS.md`, runnable scripts) |
85
- | `-p`, `--plan` | off | plan mode (`CURRENT_GOAL.md` / `CURRENT_PLAN.md`, `/plan`) |
84
+ | `--skills` | off | enable the `.mini` skills directory (`skill.md`s, `SKILLS.md`, runnable scripts). **`run_skill` executes those Python scripts — arbitrary code execution, even without `--enable-shell`**; only enable it for a directory you trust |
85
+ | `-p`, `--plan` | off | plan mode (`CURRENT_GOAL.md` / `CURRENT_PLAN.md`, printed plan, `/plan`, `/skip-plan`) |
86
+ | `--plan-strategy NAME` | `plan-verify-step` | `plan-verify-step`, `plan-verify` or `open-plan` (implies `--plan`) |
87
+ | `--scratchpad` | off | give the agent a free-form `.mini/SCRATCHPAD.md` (plus further scratch files) for thoughts, plans and learnings |
88
+ | `--compaction-strategy NAME` | `summarise` | `summarise`, `predict-files` or `predict-messages` |
86
89
  | `--llm-timeout S` | `500` | HTTP timeout for LLM requests |
87
90
  | `--tool-timeout S` | `120` | timeout for a single tool call |
88
91
  | `--max-context-tokens N` | derived | input-token budget before the history is compacted |
89
92
  | `--cache-dir DIR` | `~/.cache/mini/sessions/` | where session histories are stored |
90
93
  | `--restore-session PATH` | — | continue a specific previous session |
91
94
  | `-l`, `--load-last-session` | off | continue the session recorded in the `.mini` pointer |
92
- | `--all` | off | `--plan --enable-subagents --enable-shell --auto-mode --sudo` |
95
+ | `--all` | off | `--plan --enable-subagents --enable-shell --skills --auto-mode --sudo` |
93
96
  | `--all-last` | off | `--all` + `--load-last-session` |
94
97
  | `--verbose` | off | print full detail (default: user/assistant turns, token usage, tool calls only) |
95
98
  | `-h`, `--help` | — | show the built-in help |
@@ -132,8 +135,10 @@ mini-code --enable-subagents # the available sub-agents then show up in /h
132
135
 
133
136
  > [!NOTE]
134
137
  > A sub-agent's `tools`, `enable_shell` and `max_steps` are always **intersected with the
135
- > parent's** permissions, so it can never do anything the main agent could not. Sub-agents
136
- > compose with `--plan`: each keeps its own `CURRENT_PLAN.md` / `CURRENT_GOAL.md`.
138
+ > parent's** permissions, so it can never do anything the main agent could not. The `tools`
139
+ > allowlist is enforced on the nested session itself (both the schemas offered to the model and
140
+ > the dispatch table), not merely described in its prompt. Sub-agents compose with `--plan`:
141
+ > each keeps its own `CURRENT_PLAN.md` / `CURRENT_GOAL.md`.
137
142
 
138
143
  <details>
139
144
  <summary><b>Adding your own sub-agent</b></summary>
@@ -171,9 +176,16 @@ to the model automatically when `--enable-subagents` is set. See
171
176
  | `/reset [<n>]` | rewind to the end of turn `n` (`last` works too); drops everything after it |
172
177
  | `/clear` | clear the screen (keeps the conversation history) |
173
178
  | `/plan` | show the current goal + plan (plan mode only) |
179
+ | `/context` | show how the context window is used: tokens and percentages by category (system prompt, user/assistant messages, tool calls/outputs, reasoning, overhead) |
180
+ | `/skip-plan <prompt>` | send `<prompt>` once without generating or reviewing a plan |
174
181
  | `/help` | show this help |
175
182
  | `/quit`, `/exit` | save the session and exit |
176
183
 
184
+ **Multi-line input:** press `Shift+Enter` (or `Ctrl-J`) to insert a newline; plain
185
+ `Enter` sends the turn. This works in the session prompt and the startup tip
186
+ reminds you. Terminals that report `Shift+Enter` as a CSI-u/modifyOtherKeys
187
+ sequence are recognised; elsewhere `Ctrl-J` inserts the newline.
188
+
177
189
  > [!NOTE]
178
190
  > `/history` and `/reset` are driven by `summary_history.json`, a flat recorder that maps every
179
191
  > turn to the `history_{n}.json` segment and message index it lives in — so no full history is
@@ -232,6 +244,9 @@ command into one of three tiers:
232
244
  | **ASK** | `rm file`, `sudo ...`, `chmod`, `curl ... \| sh` | requires your confirmation |
233
245
  | **ALLOW** | `ls`, `cat`, `git status` | runs without prompting |
234
246
 
247
+ `--sudo` removes the confirmation prompts (ASK tier and `--ask-permission`); DENY commands are
248
+ still refused. With no flags, an ASK-tier command prompts and an ALLOW-tier one runs unaided.
249
+
235
250
  > [!WARNING]
236
251
  > The classifier is **always enforced** — even in auto-mode and with `--sudo` — so the agent
237
252
  > cannot run destructive commands unattended. It is a heuristic, not a sandbox: use it with care.
@@ -242,13 +257,34 @@ command into one of three tiers:
242
257
  The loop keeps two human-readable tracking files in the session directory: `CURRENT_GOAL.md`
243
258
  (your latest instruction) and `CURRENT_PLAN.md` (a step-by-step plan for that goal, marked
244
259
  finished when it is done). They are authored by the *loop*, not the agent, live outside
245
- `--allowed-dir`, and can be inspected any time with `/plan`.
260
+ `--allowed-dir`, and can be inspected any time with `/plan`. The generated plan is
261
+ also printed as a box right after planning, so you can see it without asking.
262
+ Use `/skip-plan <prompt>` to send one prompt without planning it (plan mode stays
263
+ on for later turns).
264
+
265
+ `--plan-strategy` selects how planning is wired:
266
+
267
+ | Strategy | What happens |
268
+ | --- | --- |
269
+ | `plan-verify-step` (default) | Current behaviour: author a plan, review it once the work settles, then run one extra step and keep whatever that step says. |
270
+ | `plan-verify` | Same plan + review, but the post-review step is kept only when it calls a tool. A no-tool answer is shown to you and ends the turn without being appended to the transcript. |
271
+ | `open-plan` | The agent owns a plan document at `.mini/PLAN.md` inside `--allowed-dir`, reads and updates it with the normal file tools, and the loop neither authors nor reviews a plan. |
246
272
 
247
273
  > [!NOTE]
248
274
  > Plan mode also changes **history compaction**: after the transcript is compacted to a summary,
249
275
  > `CURRENT_PLAN.md` and `CURRENT_GOAL.md` are re-injected, so the agent keeps working against the
250
- > same goal. When the work looks done the plan is reviewed and any outstanding task is re-queued
251
- > before the agent returns to you.
276
+ > same goal. With `open-plan`, the agent's `.mini/PLAN.md` is re-injected instead. When the work
277
+ > looks done the plan is reviewed and any outstanding task is re-queued before the agent returns
278
+ > to you (except with `open-plan`).
279
+
280
+ ### Scratchpad — `--scratchpad`
281
+
282
+ With `--scratchpad`, the loop creates `.mini/SCRATCHPAD.md` inside `--allowed-dir` and tells the
283
+ agent that it may read and write that file freely, and may create additional scratch files in the
284
+ same directory (for example `SCRATCH-NOTES.md`, `SCRATCH-IDEAS.md`). The scratchpad is ordinary
285
+ state inside the sandbox, so the normal `read_file` / `write_file` / `edit` tools work; no special
286
+ tool is registered. It is meant for the agent's own thoughts, plans, learnings and open questions,
287
+ and survives a history compaction because it lives on disk.
252
288
 
253
289
  ### Sessions — resume, or start fresh
254
290
 
@@ -296,6 +332,20 @@ waiting on) is kept verbatim after the summary. So a compaction that fires just
296
332
  instruction cannot swallow it — the model still answers what you asked, and the turn stays in
297
333
  the session file, in `/history` and in a later restore.
298
334
 
335
+ `--compaction-strategy` chooses what else survives besides the summary:
336
+
337
+ | Strategy | Messages after compaction |
338
+ | --- | --- |
339
+ | `summarise` (default) | `system`, `summary`, `plan`, `current turn` |
340
+ | `predict-files` | `system`, `summary`, predicted read-only tool calls + results, `plan`, `current turn` |
341
+ | `predict-messages` | `system`, `summary`, original messages the model names by index, `plan`, `current turn` |
342
+
343
+ `predict-files` asks the model which files it needs to re-read and executes only the read-only
344
+ tools (`read_file`, `grep`, `glob`) it predicts; `predict-messages` asks for a JSON array of
345
+ 0-based message indexes to keep verbatim. Both predictions are one extra tool-free (or
346
+ read-only-tool) LLM call, are billed normally, and are capped so they cannot refill the context
347
+ they just freed. A failed prediction degrades to the plain summary.
348
+
299
349
  Because a rollover leaves no trace in the transcript (the old turns really are gone), the
300
350
  console says in plain terms what happened — all of it without `--verbose`:
301
351
 
@@ -360,7 +410,7 @@ If you use `mini-code-cli` in your research or writing, please cite it:
360
410
  author = {Rozanov, Nikolai},
361
411
  title = {mini-code-cli: A minimal, dependency-light coding agent},
362
412
  year = {2026},
363
- version = {0.1.1.2},
413
+ version = {0.1.1.4},
364
414
  howpublished = {\url{https://github.com/ai-nikolai/mini-code-cli}},
365
415
  note = {A no-bloat, dependency-light agent CLI for experimenting.}
366
416
  }
@@ -0,0 +1,90 @@
1
+ """Agent-owned files kept in ``--allowed-dir/.mini``.
2
+
3
+ Two opt-in features put a file the *agent* may read and write there, rather
4
+ than in the session directory the loop owns:
5
+
6
+ * the **scratchpad** (``--scratchpad``): a free-form note file for thoughts,
7
+ plans and learnings, plus as many additional scratch files as the agent
8
+ wants to create;
9
+ * the **open plan** (``--plan-strategy open-plan``): a plan document the
10
+ agent maintains itself with the normal file tools.
11
+
12
+ Both live under the same ``.mini`` directory as the skills folder and the
13
+ latest-session pointer, so they are inside the ``--allowed-dir`` sandbox and
14
+ the normal ``read_file`` / ``write_file`` / ``edit`` tools can reach them. The
15
+ directory name is read from :mod:`mini_code_cli.persistence` at call time, so
16
+ the test suite can redirect it globally (exactly like the session pointer).
17
+ """
18
+
19
+ import os
20
+
21
+ from . import persistence
22
+
23
+ SCRATCHPAD_FILENAME = "SCRATCHPAD.md"
24
+ OPEN_PLAN_FILENAME = "PLAN.md"
25
+
26
+ _SCRATCHPAD_HEADER = """# Scratchpad
27
+
28
+ This file belongs to the agent. It may read and write it freely and may create
29
+ additional scratch files in the same directory. Use it for thoughts, plans,
30
+ learnings and notes that should survive a compaction.
31
+ """
32
+
33
+ _OPEN_PLAN_HEADER = """# Agent Plan
34
+
35
+ This plan document belongs to the agent. Read it before continuing, keep it up
36
+ to date as work progresses, and mark steps done or outstanding.
37
+ """
38
+
39
+
40
+ def mini_dir(allowed_dir):
41
+ """The ``.mini`` directory inside ``allowed_dir`` (not created)."""
42
+ return os.path.join(os.path.abspath(allowed_dir), persistence.SESSION_DIRNAME)
43
+
44
+
45
+ def scratchpad_path(allowed_dir):
46
+ """Path to the main scratch-pad file."""
47
+ return os.path.join(mini_dir(allowed_dir), SCRATCHPAD_FILENAME)
48
+
49
+
50
+ def open_plan_path(allowed_dir):
51
+ """Path to the agent-authored plan document."""
52
+ return os.path.join(mini_dir(allowed_dir), OPEN_PLAN_FILENAME)
53
+
54
+
55
+ def ensure_scratchpad(allowed_dir):
56
+ """Create the main scratch-pad file (and its directory) if missing."""
57
+ return _ensure_file(scratchpad_path(allowed_dir), _SCRATCHPAD_HEADER)
58
+
59
+
60
+ def ensure_open_plan(allowed_dir):
61
+ """Create the agent plan document (and its directory) if missing."""
62
+ return _ensure_file(open_plan_path(allowed_dir), _OPEN_PLAN_HEADER)
63
+
64
+
65
+ def read_text(path, limit=None):
66
+ """Read ``path`` as text, returning ``""`` when it cannot be read.
67
+
68
+ ``limit`` caps the returned characters (the open-plan re-injection after a
69
+ compaction should not be able to re-fill the context with the document).
70
+ """
71
+ try:
72
+ with open(path, "r", encoding="utf-8", errors="replace") as handle:
73
+ text = handle.read()
74
+ except OSError:
75
+ return ""
76
+ if limit is not None and len(text) > limit:
77
+ return text[:limit] + "\n[... truncated ...]\n"
78
+ return text
79
+
80
+
81
+ def _ensure_file(path, header):
82
+ """Best-effort create-with-header; never raises, always returns ``path``."""
83
+ try:
84
+ if not os.path.isfile(path):
85
+ os.makedirs(os.path.dirname(path), exist_ok=True)
86
+ with open(path, "w", encoding="utf-8") as handle:
87
+ handle.write(header)
88
+ except OSError:
89
+ pass
90
+ return path