mini-coder 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,8 @@
2
2
 
3
3
  ## Bugs
4
4
 
5
- - `/model` doesn't autocomplete models provider/name pattern.
6
5
  - AI SDK expands `claude-3-5-haiku` → dated variant that Zen doesn't serve (404).
7
- - Shell tool max-timeout leaves the parent terminal in a broken state.
6
+ - Shell tool: model can `tmux kill-session` the host tmux session if names collide (e.g. audit skill creates session named "audit" matching the user's). Not a code bug — the skill/model just picks a conflicting name. Mitigate via skill wording or session name prefixing.
8
7
 
9
8
  ## Features
10
9
 
@@ -0,0 +1,74 @@
1
+ # Design Decisions
2
+
3
+ Documenting why mini-coder makes certain architectural choices — especially where we intentionally diverge from AI SDK defaults or common patterns.
4
+
5
+ ## Why not ToolLoopAgent?
6
+
7
+ **Decision:** Use `streamText` directly instead of the AI SDK's `ToolLoopAgent`.
8
+
9
+ `ToolLoopAgent` is a convenience wrapper that manages the tool-call loop, context, and stopping conditions. Mini-coder needs explicit control over every aspect it abstracts away:
10
+
11
+ - **Streaming event rendering** — We yield granular `TurnEvent`s (text deltas, tool calls, tool results, reasoning, context-pruned notifications) as they arrive from `fullStream`. The reporter renders them append-only into the terminal in real time. `ToolLoopAgent` gives you the final result; we need the firehose.
12
+ - **ESC interrupt mid-turn** — An `AbortController` is wired through to `streamText`'s `signal`. On ESC, we abort, preserve partial messages, and append an interrupt stub so the LLM retains context. `ToolLoopAgent` doesn't expose this kind of mid-stream abort-and-preserve behavior.
13
+ - **Custom context pruning** — After every turn, `SessionRunner` runs `applyContextPruning` + `compactToolResultPayloads` on the in-memory history. This is rolling, per-turn pruning that must not break prompt caching. `ToolLoopAgent`'s built-in context management doesn't match these constraints.
14
+ - **Per-step DB persistence** — Each turn's messages are saved to SQLite with a turn index as they complete. The in-memory `coreHistory` diverges from the DB history (pruned vs. full). `ToolLoopAgent` has no hook for this.
15
+ - **Provider-specific caching annotations** — `annotateToolCaching` adds caching metadata to the tool set based on the model string, injected directly into the `streamText` call.
16
+ - **No step/tool-call limits** — Per the design: "No max steps or tool call limits — user can interrupt." `ToolLoopAgent` defaults to `stopWhen: stepCountIs(20)`.
17
+
18
+ **Summary:** `ToolLoopAgent` reduces boilerplate for simple request→response agents. Mini-coder is a shell-first coding agent where the loop _is_ the product. Using `ToolLoopAgent` would mean fighting the abstraction at every turn.
19
+
20
+ ## Why no cross-session memory?
21
+
22
+ **Decision:** No agent-managed persistent memory across sessions. The repo and user-authored config files are the memory.
23
+
24
+ The AI SDK offers several memory approaches (Anthropic memory tool, Mem0, Letta, custom tools) that let agents save facts and recall them in future conversations. We intentionally don't use any of these.
25
+
26
+ ### What we have instead
27
+
28
+ - **Within-session persistence** — Full message history saved to SQLite per-turn, sessions resumable via `/session`.
29
+ - **Context pruning** — `applyContextPruning` and `applyStepPruning` strip old reasoning/tool-calls to fit context windows without breaking prompt caching.
30
+ - **Static cross-session context** — `AGENTS.md`/`CLAUDE.md` files loaded into the system prompt. This is user-curated project knowledge, not agent-managed memory.
31
+ - **Skills** — Reusable instruction sets discoverable via `/` autocomplete.
32
+
33
+ ### Why not agent-written memory?
34
+
35
+ We considered having the agent write to `~/.agents/AGENTS.md` for cross-session recall. Rejected because:
36
+
37
+ - **Intrusive** — `~/.agents/` is the user's space. Agent writes would mix generated noise with intentional configuration, creating surprises ("where did this line come from?").
38
+ - **Violates conventions** — `AGENTS.md`/`CLAUDE.md` are community standards meant to be human-authored instructions _to_ the agent, not an agent scratchpad. Using them as memory inverts the relationship.
39
+ - **Safety conflict** — Our own system prompt requires confirmation before irreversible actions. Silently modifying a user's global config violates that principle.
40
+ - **Complexity** — Memory adds storage, retrieval, relevance ranking, and non-determinism. The design philosophy is performance first, minimal setup.
41
+
42
+ ### If we ever want this
43
+
44
+ A dedicated `~/.config/mini-coder/memories.md` that's clearly agent-owned and separate from user config would be the right path — not overloading existing community standards.
45
+
46
+ **Summary:** For a coding agent that operates on a repo, the repo _is_ the memory. Users who want cross-session context write it in `AGENTS.md` themselves — that's an intentional act, not an LLM side effect.
47
+
48
+ ## Why no tool-call permissions?
49
+
50
+ **Decision:** No approval prompts, no blacklists, no whitelists. Every tool call executes immediately.
51
+
52
+ Our inspirations (Claude Code, OpenCode) require user approval for tool calls — shell commands, file writes, etc. We intentionally skip this.
53
+
54
+ ### Permission systems provide a false sense of security
55
+
56
+ - **Shell bypasses everything.** An LLM with shell access can `curl`, `eval`, pipe through `bash`, encode payloads, or chain commands in ways no static blacklist can anticipate. Any permission scheme that allows shell but blocks specific patterns is playing whack-a-mole.
57
+ - **Blacklists and whitelists always have gaps.** Block `rm -rf /`? The model uses `find -delete`. Block `git push --force`? It uses `git push origin +main`. The surface area is unbounded.
58
+ - **Approval fatigue degrades security.** After the 20th "Allow shell command?" prompt, users auto-approve everything. The permission system trains the user to click "yes" reflexively — the opposite of its intent.
59
+
60
+ ### Permissions are cumbersome
61
+
62
+ A coding agent runs dozens of shell commands per task. Requiring approval for each one destroys the flow that makes a CLI agent useful. The whole point of mini-coder is: small, fast, stays out of the way.
63
+
64
+ ### Isolation is a separate concern
65
+
66
+ Sandboxing is a real need, but it belongs at the OS/container level — not inside the agent. Tools like [nono](https://nono.sh/) provide proper filesystem and network isolation that the LLM cannot circumvent. This is defense in depth done right: the agent runs unrestricted inside a sandbox that enforces actual boundaries.
67
+
68
+ ### Our approach
69
+
70
+ - The system prompt includes safety rules (no secrets, confirm destructive actions, no unauthorized reverts).
71
+ - The user can interrupt at any time with ESC (preserve context) or Ctrl+C (hard exit).
72
+ - For real isolation, run mini-coder inside a sandboxed environment.
73
+
74
+ **Summary:** Permission dialogs give the appearance of safety without the substance. Real security comes from sandboxing the environment, not gatekeeping individual tool calls. Mini-coder codes — isolating it is a job for the right tool.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mini-coder",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "A small, fast CLI coding agent",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",
@@ -31,6 +31,7 @@
31
31
  "diff": "^8.0.3",
32
32
  "yoctocolors": "^2.1.2",
33
33
  "yoctomarkdown": "^0.0.7",
34
+ "yoctoselect": "0.0.3",
34
35
  "zod": "^4.3.6"
35
36
  },
36
37
  "devDependencies": {