mini-code-cli 0.1.0.4__tar.gz → 0.1.1.1__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.
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/PKG-INFO +253 -138
- mini_code_cli-0.1.1.1/README.md +326 -0
- mini_code_cli-0.1.1.1/mini_code_cli/__init__.py +40 -0
- mini_code_cli-0.1.1.1/mini_code_cli/agent_loop.py +2129 -0
- mini_code_cli-0.1.1.1/mini_code_cli/config.py +231 -0
- mini_code_cli-0.1.1.1/mini_code_cli/persistence.py +547 -0
- mini_code_cli-0.1.1.1/mini_code_cli/plan.py +156 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/prompts.py +12 -5
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/sandbox.py +6 -2
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/skills.py +6 -2
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/subagents/base.py +44 -15
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/subagents/builtin.py +2 -2
- mini_code_cli-0.1.1.1/mini_code_cli/tokens.py +118 -0
- mini_code_cli-0.1.1.1/mini_code_cli/tools.py +672 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/ui.py +69 -13
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/utils.py +79 -20
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli.egg-info/PKG-INFO +253 -138
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli.egg-info/SOURCES.txt +5 -1
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/pyproject.toml +9 -1
- mini_code_cli-0.1.1.1/tests/test_e2e_agent_loop.py +1127 -0
- mini_code_cli-0.1.1.1/tests/test_interactive.py +1008 -0
- mini_code_cli-0.1.1.1/tests/test_subagents.py +372 -0
- mini_code_cli-0.1.1.1/tests/test_tokens.py +410 -0
- mini_code_cli-0.1.0.4/README.md +0 -217
- mini_code_cli-0.1.0.4/mini_code_cli/__init__.py +0 -2
- mini_code_cli-0.1.0.4/mini_code_cli/agent_loop.py +0 -1406
- mini_code_cli-0.1.0.4/mini_code_cli/config.py +0 -19
- mini_code_cli-0.1.0.4/mini_code_cli/persistence.py +0 -321
- mini_code_cli-0.1.0.4/mini_code_cli/plan.py +0 -218
- mini_code_cli-0.1.0.4/mini_code_cli/tools.py +0 -308
- mini_code_cli-0.1.0.4/tests/test_e2e_agent_loop.py +0 -557
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/LICENSE +0 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/permissions.py +0 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/runner.py +0 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/shell_safety_utils.py +0 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli/subagents/__init__.py +0 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli.egg-info/dependency_links.txt +0 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli.egg-info/entry_points.txt +0 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli.egg-info/requires.txt +0 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/mini_code_cli.egg-info/top_level.txt +0 -0
- {mini_code_cli-0.1.0.4 → mini_code_cli-0.1.1.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mini-code-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1.1
|
|
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: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
@@ -666,95 +666,159 @@ License: GNU AFFERO GENERAL PUBLIC LICENSE
|
|
|
666
666
|
<https://www.gnu.org/licenses/>.
|
|
667
667
|
|
|
668
668
|
Project-URL: Homepage, https://github.com/ai-nikolai/mini-code-cli
|
|
669
|
+
Classifier: Programming Language :: Python :: 3
|
|
670
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
671
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
672
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
673
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
674
|
+
Classifier: Operating System :: OS Independent
|
|
669
675
|
Requires-Python: >=3.10
|
|
670
676
|
Description-Content-Type: text/markdown
|
|
671
677
|
License-File: LICENSE
|
|
672
678
|
Requires-Dist: requests<3,>=2.31
|
|
673
679
|
Dynamic: license-file
|
|
674
680
|
|
|
675
|
-
#
|
|
681
|
+
# mini-code-cli
|
|
682
|
+
|
|
683
|
+
### A minimal coding agent CLI
|
|
676
684
|
|
|
677
685
|
> No bloat, no dependencies, no tracking, no telemetry...
|
|
678
686
|
|
|
679
|
-
|
|
687
|
+
[](https://github.com/ai-nikolai/mini-code-cli/actions/workflows/ci.yml)
|
|
688
|
+
[](https://pypi.org/project/mini-code-cli/)
|
|
689
|
+
[](https://pypi.org/project/mini-code-cli/)
|
|
690
|
+
[](https://github.com/ai-nikolai/mini-code-cli/stargazers)
|
|
691
|
+
[](LICENSE)
|
|
692
|
+
[](#citation)
|
|
693
|
+
|
|
694
|
+
**Purpose:** a no-bloat, minimal coding CLI to enjoy experimenting and researching.
|
|
695
|
+
|
|
696
|
+
**Install** · [Quick start](#quick-start) · [Modes & safety](#modes--safety) · [Options](#command-line-options) · [Tools](#available-tools) · [Sub-agents](#sub-agents) · [In-session commands](#in-session-commands) · [Development](#development) · [Docs](#documentation) · [Citation](#citation)
|
|
680
697
|
|
|
681
|
-
|
|
698
|
+
> [!TIP]
|
|
699
|
+
> **New here?** `pip install mini-code-cli`, point it at a model (a local server on
|
|
700
|
+
> `localhost:30000`, or `MINI_CODE_API_KEY` + `--url`), and run `mini-code`. Everything else
|
|
701
|
+
> is optional.
|
|
702
|
+
|
|
703
|
+
## Install
|
|
682
704
|
|
|
683
|
-
### Installation (from pypi)
|
|
684
705
|
```bash
|
|
685
706
|
pip3 install mini-code-cli
|
|
686
707
|
```
|
|
687
708
|
|
|
688
|
-
|
|
709
|
+
- **PyPI:** <https://pypi.org/project/mini-code-cli/>
|
|
710
|
+
- **Python:** `>= 3.10` · **runtime dependency:** `requests` only
|
|
711
|
+
- **From source / contributing:** see [docs/README_DEV.md](docs/README_DEV.md)
|
|
712
|
+
|
|
713
|
+
## Quick start
|
|
714
|
+
|
|
715
|
+
**1 — Local model** (e.g. vLLM or SGLang on port 30000; see [serving a model locally](#serving-a-model-locally)):
|
|
689
716
|
|
|
690
|
-
1. Basic usage: (get local LLM running (e.g. via SGLang or Vllm))
|
|
691
717
|
```bash
|
|
692
|
-
mini-code
|
|
718
|
+
mini-code # talks to http://0.0.0.0:30000/v1
|
|
693
719
|
```
|
|
694
|
-
|
|
720
|
+
|
|
721
|
+
**2 — Hosted / custom API:**
|
|
722
|
+
|
|
695
723
|
```bash
|
|
696
724
|
export MINI_CODE_API_KEY="sk-YOUR_API_KEY"
|
|
697
725
|
mini-code --url "https://api.deepseek.com" --model "deepseek-v4-flash"
|
|
698
726
|
```
|
|
699
|
-
3. Auto-mode and shell enabled: (this will run localhost:30000)
|
|
700
|
-
```bash
|
|
701
|
-
mini-code --enable-shell --auto-mode
|
|
702
|
-
mini-code -s -a --sudo
|
|
703
|
-
mini-code -s -a -p -g -l --sudo #plan, previous session, subagents (#or short-hand the next commands)
|
|
704
|
-
mini-code --all
|
|
705
|
-
mini-code --all-last
|
|
706
|
-
```
|
|
707
727
|
|
|
708
|
-
|
|
709
|
-
|
|
728
|
+
**3 — The shortcuts** (plan mode, sub-agents, shell, auto-mode, no permission prompts):
|
|
729
|
+
|
|
710
730
|
```bash
|
|
711
|
-
mini-code --
|
|
731
|
+
mini-code --all # = --plan --enable-subagents --enable-shell --auto-mode --sudo
|
|
732
|
+
mini-code --all-last # ...and continue your last session
|
|
712
733
|
```
|
|
713
|
-
- auto-mode: the agent will continue querying the LLM and executing tools, until no more tool calls are possible
|
|
714
|
-
- agent.md: this will read an agent.md file with the specified name (e.g. ./skill.md)
|
|
715
|
-
- shell-enabled: **Be careful**: This will allow the agent to execute shell commands. **Every command is first checked by a shell-safety classifier** that sorts it into three tiers:
|
|
716
|
-
- **DENY** — obviously destructive commands (e.g. `rm -rf /`, `dd of=/dev/...`, `mkfs.*`, fork bombs) are **refused outright** and never run.
|
|
717
|
-
- **ASK** — risky commands (e.g. `rm file`, `sudo ...`, `chmod`, `curl ... | sh`) require your confirmation before running.
|
|
718
|
-
- **ALLOW** — clearly safe commands (e.g. `ls`, `cat`, `git status`) run without prompting.
|
|
719
|
-
This protection is **always enforced** for the shell tool, even in auto-mode / without `--ask-permission`, so the agent can never run dangerous commands unattended. (The classifier is a heuristic, not a sandbox — use with care.)
|
|
720
|
-
- allowed-dir: this specifies which dirs the agent can read and write from, that does not stop the shell comands! (though dangerous shell commands are still blocked by the classifier above).
|
|
721
|
-
- ask-permission: asks user permission before every tool call. For shell commands, commands in the ALLOW tier skip the prompt, DENY is blocked, and ASK always prompts.
|
|
722
|
-
- system-prompt: you can override the default prompt by using a string. (Note: Agent.md is always appended after the system prompt.)
|
|
723
|
-
- load-last-session: instead of starting a fresh conversation, automatically continue your most recently active session from the default cache dir. It resumes under a brand-new session id, so the original session is never overwritten. An explicit `--restore-session` (a specific path) takes precedence if both are given. The "most recent" session is resolved in two steps: at the end of every interactive session, its path is recorded in a tiny `.mini/last_session.json` pointer inside the `--allowed-dir`, and `--load-last-session` consults that pointer first; only if there is no pointer (e.g. a fresh allowed dir, or the `--skills` feature disabled) does it fall back to the timestamp heuristic (the session whose history was modified most recently). The `.mini` pointer is the same directory the `--skills` feature uses, but it is a single dedicated file, so the two never clash.
|
|
724
|
-
- **Interactive session offer:** if a previous session exists in the cache dir but you did **not** explicitly ask to resume one (i.e. neither `--load-last-session` nor `--restore-session` was passed), the prompt asks what you'd like to do before the conversation starts: 1) **Resume** the previous session (splice its history in under a brand-new session id and continue it), 2) **Start a new** session (empty history), or 3) **Exit** (start nothing). Ctrl-C / EOF at the offer is treated as a graceful exit. This is distinct from `--load-last-session`, which silently resumes the most recent session without asking.
|
|
725
|
-
- plan: `--plan` enables **plan mode**. The loop keeps two human-readable tracking files in the session directory: `CURRENT_GOAL.md` (the user's latest instruction) and `CURRENT_PLAN.md` (a step-by-step plan the loop generates for the active goal, marked finished once the goal is done). These files are authored by the *loop*, not the agent (they live outside `--allowed-dir`), and you can inspect them anytime with `/plan` (only meaningful in plan mode). After the work looks done, plan mode reviews the plan's completion and re-queues any outstanding tasks before returning to you. Plan mode also changes how history compaction works: after the history is compacted to a summary, the current `CURRENT_PLAN.md` and the user's last instruction (`CURRENT_GOAL.md`) are re-injected into the messages so the agent keeps working against the same goal. When the session ends, the active goal is marked finished in `CURRENT_PLAN.md`.
|
|
726
734
|
|
|
727
|
-
|
|
735
|
+
**4 — A first prompt:**
|
|
728
736
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
- **`glob`** — list files matching a glob pattern.
|
|
734
|
-
- **`web_search`** — best-effort web lookup: returns popular related queries (DuckDuckGo autocomplete) plus a short extract from the top Wikipedia match. Never raises; always returns a string.
|
|
735
|
-
- **`read_website`** — fetch the raw text/HTML of a URL (bounded by `--tool-timeout`).
|
|
736
|
-
- **`run_shell_command`** — run a shell command (only when `--enable-shell` is set). Every command is passed through the shell-safety classifier described above.
|
|
737
|
-
|
|
738
|
-
### Sub-agents
|
|
739
|
-
|
|
740
|
-
Passing `--enable-subagents` lets the main agent **delegate a focused task to a sub-agent**, which is exposed to the model as an extra tool. A sub-agent is a self-contained, narrowed agent: it runs on its own in auto-mode (unattended), in its own isolated session folder, and hands a short text result (plus an optional `report.md`) back to the main agent. It reuses all the existing machinery -- tools, the shell-safety classifier, the `--allowed-dir` sandbox, history compaction and `--plan` mode -- and cannot recursively spawn further sub-agents.
|
|
737
|
+
```txt
|
|
738
|
+
Write an agent.md file for me that helps an LLM write efficient triton kernels,
|
|
739
|
+
given a reference implementation.
|
|
740
|
+
```
|
|
741
741
|
|
|
742
|
-
|
|
742
|
+
> [!NOTE]
|
|
743
|
+
> **Every flag** is listed once, in [Command-line options](#command-line-options) — or run
|
|
744
|
+
> `mini-code --help`. Modes and their caveats are described in [Modes & safety](#modes--safety).
|
|
745
|
+
|
|
746
|
+
## Command-line options
|
|
747
|
+
|
|
748
|
+
| Option | Default | What it does |
|
|
749
|
+
| --- | --- | --- |
|
|
750
|
+
| `--url URL` | `http://0.0.0.0:30000` | API host |
|
|
751
|
+
| `--model MODEL` | — | model name |
|
|
752
|
+
| `--api-key KEY` | `$MINI_CODE_API_KEY` | API key for authentication |
|
|
753
|
+
| `--max-tokens N` | — | reply budget; also the output headroom used when deriving the compaction limit |
|
|
754
|
+
| `--temperature T` | `1.0` | sampling temperature |
|
|
755
|
+
| `--system-prompt TEXT` | built-in | replace the system prompt (an `--agent-md` file is appended *after* it) |
|
|
756
|
+
| `--prompt TEXT` | — | initial user prompt |
|
|
757
|
+
| `-a`, `--auto-mode` | off | keep querying the model and running tools until no tool calls remain |
|
|
758
|
+
| `--agent-md FILE` | — | append an `agent.md` file after the system prompt (e.g. `./skill.md`) |
|
|
759
|
+
| `--ask-permission` | off | ask before every tool call (ALLOW-tier shell commands still skip the prompt) |
|
|
760
|
+
| `--sudo` | off | **dangerous:** never ask. DENY-tier commands are still refused |
|
|
761
|
+
| `--allowed-dir DIR` | `./` | sandbox for **file** tools (does not restrict the shell) |
|
|
762
|
+
| `-s`, `--enable-shell` | off | allow shell execution (classifier always applies) |
|
|
763
|
+
| `-g`, `--enable-subagents` | off | expose sub-agents as tools |
|
|
764
|
+
| `--skills` | off | enable the `.mini` skills directory (`skill.md`s, `SKILLS.md`, runnable scripts) |
|
|
765
|
+
| `-p`, `--plan` | off | plan mode (`CURRENT_GOAL.md` / `CURRENT_PLAN.md`, `/plan`) |
|
|
766
|
+
| `--llm-timeout S` | `500` | HTTP timeout for LLM requests |
|
|
767
|
+
| `--tool-timeout S` | `120` | timeout for a single tool call |
|
|
768
|
+
| `--max-context-tokens N` | derived | input-token budget before the history is compacted |
|
|
769
|
+
| `--cache-dir DIR` | `~/.cache/mini/sessions/` | where session histories are stored |
|
|
770
|
+
| `--restore-session PATH` | — | continue a specific previous session |
|
|
771
|
+
| `-l`, `--load-last-session` | off | continue the session recorded in the `.mini` pointer |
|
|
772
|
+
| `--all` | off | `--plan --enable-subagents --enable-shell --auto-mode --sudo` |
|
|
773
|
+
| `--all-last` | off | `--all` + `--load-last-session` |
|
|
774
|
+
| `--verbose` | off | print full detail (default: user/assistant turns, token usage, tool calls only) |
|
|
775
|
+
| `-h`, `--help` | — | show the built-in help |
|
|
776
|
+
|
|
777
|
+
## Available tools
|
|
778
|
+
|
|
779
|
+
The agent can call a small set of tools, all defined in `mini_code_cli/tools.py`. Every
|
|
780
|
+
parameter a model does not need is defaulted, so omitting it keeps the previous behaviour.
|
|
781
|
+
|
|
782
|
+
| Tool | What it does |
|
|
783
|
+
| --- | --- |
|
|
784
|
+
| `read_file` | read a file; `offset` (1-based line) and `limit` page through large files |
|
|
785
|
+
| `write_file` | write/overwrite; `append` adds to the end, `create_dirs` creates parents |
|
|
786
|
+
| `edit` | replace an **exact** string (`old_string` → `new_string`); refuses a missing or ambiguous match unless `replace_all` |
|
|
787
|
+
| `grep` | regex search a file or directory; `recursive`, `include`, `ignore_case`, `line_numbers`, `max_results` (noise dirs skipped) |
|
|
788
|
+
| `glob` | list files matching a glob (one per line, `**` supported), optionally against a `root` |
|
|
789
|
+
| `web_search` | best-effort lookup: related queries + a short Wikipedia extract. Never raises |
|
|
790
|
+
| `read_website` | fetch raw text/HTML of a URL (bounded by `--tool-timeout`), `max_chars` caps size |
|
|
791
|
+
| `run_shell_command` | run a shell command (needs `--enable-shell`); `cwd`, `timeout`, and stdout/stderr/exit code are all reported |
|
|
792
|
+
|
|
793
|
+
## Sub-agents
|
|
794
|
+
|
|
795
|
+
`--enable-subagents` lets the main agent **delegate a focused task** to a sub-agent, exposed to
|
|
796
|
+
the model as an extra tool. A sub-agent is a self-contained, narrowed agent: it runs unattended
|
|
797
|
+
in auto-mode, in its own isolated session folder, and hands back a short text result (plus an
|
|
798
|
+
optional `report.md`). It reuses all the existing machinery — tools, the shell-safety
|
|
799
|
+
classifier, the `--allowed-dir` sandbox, compaction and `--plan` — and cannot spawn further
|
|
800
|
+
sub-agents.
|
|
743
801
|
|
|
744
802
|
```bash
|
|
745
|
-
mini-code --enable-subagents
|
|
803
|
+
mini-code --enable-subagents # the available sub-agents then show up in /help
|
|
746
804
|
```
|
|
747
805
|
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
806
|
+
| Sub-agent | What it is for |
|
|
807
|
+
| --- | --- |
|
|
808
|
+
| `research` | read-only web research: searches, reads a few sources, returns a sourced summary. Can only use `web_search` / `read_website` — never the filesystem or shell. Optional `sources` hint (e.g. `"wikipedia.org only"`) |
|
|
809
|
+
| `planner` | drafts or refines a step-by-step plan for a goal; always runs in plan mode |
|
|
810
|
+
| `software_engineer` | writes, edits, refactors, fixes and tests code; can run shell commands (tests, builds) to verify |
|
|
811
|
+
| `generic` | general-purpose helper for anything that fits no narrower agent |
|
|
752
812
|
|
|
753
|
-
|
|
813
|
+
> [!NOTE]
|
|
814
|
+
> A sub-agent's `tools`, `enable_shell` and `max_steps` are always **intersected with the
|
|
815
|
+
> parent's** permissions, so it can never do anything the main agent could not. Sub-agents
|
|
816
|
+
> compose with `--plan`: each keeps its own `CURRENT_PLAN.md` / `CURRENT_GOAL.md`.
|
|
754
817
|
|
|
755
|
-
|
|
818
|
+
<details>
|
|
819
|
+
<summary><b>Adding your own sub-agent</b></summary>
|
|
756
820
|
|
|
757
|
-
A sub-agent is just a small class
|
|
821
|
+
A sub-agent is just a small class — subclass `SubAgent` and register it:
|
|
758
822
|
|
|
759
823
|
```python
|
|
760
824
|
# my_subagents.py
|
|
@@ -770,98 +834,147 @@ class SummarizeSubAgent(SubAgent):
|
|
|
770
834
|
register(SummarizeSubAgent())
|
|
771
835
|
```
|
|
772
836
|
|
|
773
|
-
|
|
837
|
+
Make sure the module is imported (e.g. `import my_subagents`) and it is discovered and exposed
|
|
838
|
+
to the model automatically when `--enable-subagents` is set. See
|
|
839
|
+
`mini_code_cli/subagents/builtin.py` for every knob and
|
|
840
|
+
[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) (sections 2–3) for the design.
|
|
841
|
+
|
|
842
|
+
</details>
|
|
843
|
+
|
|
844
|
+
## In-session commands
|
|
845
|
+
|
|
846
|
+
| Command | What it does |
|
|
847
|
+
| --- | --- |
|
|
848
|
+
| `/history` | list the conversation (turn number, what happened, where) |
|
|
849
|
+
| `/history <n>` | show the full messages recorded for turn `n` |
|
|
850
|
+
| `/history last` | ...for the most recent turn |
|
|
851
|
+
| `/reset [<n>]` | rewind to the end of turn `n` (`last` works too); drops everything after it |
|
|
852
|
+
| `/clear` | clear the screen (keeps the conversation history) |
|
|
853
|
+
| `/plan` | show the current goal + plan (plan mode only) |
|
|
854
|
+
| `/help` | show this help |
|
|
855
|
+
| `/quit`, `/exit` | save the session and exit |
|
|
856
|
+
|
|
857
|
+
> [!NOTE]
|
|
858
|
+
> `/history` and `/reset` are driven by `summary_history.json`, a flat recorder that maps every
|
|
859
|
+
> turn to the `history_{n}.json` segment and message index it lives in — so no full history is
|
|
860
|
+
> read just to list the conversation.
|
|
861
|
+
>
|
|
862
|
+
> * **`<n>` is validated**: `last`, or a positive 1-based turn number. `0`, negatives and
|
|
863
|
+
> non-numbers are rejected with `No such turn` instead of silently showing a different turn.
|
|
864
|
+
> * **A bare `/reset` never destroys anything**: it reports `Already at turn N` when the
|
|
865
|
+
> transcript already ends at the last recorded turn, and *warns instead of truncating* if
|
|
866
|
+
> there are messages that were never recorded. Only `/reset <n>` / `/reset last` rewind.
|
|
867
|
+
> * **A rewind really sticks**: the target `history_{n}.json` is truncated in place (no backup)
|
|
868
|
+
> and every higher `history_{m}.json` / `usage_{m}.json` segment is deleted, so a restart
|
|
869
|
+
> cannot resurrect the dropped turns. All history files are written atomically.
|
|
870
|
+
> * **Token usage is never rolled back**: a rewind does not un-spend tokens, and the session
|
|
871
|
+
> total is preserved. See
|
|
872
|
+
> [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md#rewinding-reset-and-what-it-does-to-the-files)
|
|
873
|
+
> for the files involved.
|
|
874
|
+
|
|
875
|
+
## Development
|
|
876
|
+
|
|
877
|
+
Linting, the test suite, CI and the release process are documented in
|
|
878
|
+
[**docs/README_DEV.md**](docs/README_DEV.md).
|
|
774
879
|
|
|
775
|
-
3. Try a prompt:
|
|
776
|
-
```txt
|
|
777
|
-
Write an agent.md file for me that helps an LLM write efficient triton kernels, given a reference implementation.
|
|
778
|
-
```
|
|
779
|
-
|
|
780
|
-
4. Get help:
|
|
781
880
|
```bash
|
|
782
|
-
|
|
881
|
+
python3 scripts/lint.py # lint (standard library only)
|
|
882
|
+
python3 -m unittest discover -s tests -p "test_*.py" # run the test suite
|
|
783
883
|
```
|
|
784
|
-
```
|
|
785
|
-
Agent loop for interacting with a language model
|
|
786
|
-
|
|
787
|
-
options:
|
|
788
|
-
-h, --help show this help message and exit
|
|
789
|
-
--url URL API host, default=http://0.0.0.0:30000
|
|
790
|
-
--max-tokens MAX_TOKENS
|
|
791
|
-
Maximum tokens for LLM response, default=None
|
|
792
|
-
--temperature TEMPERATURE
|
|
793
|
-
Temperature for LLM, default=1.0
|
|
794
|
-
--model MODEL Model name, default=None
|
|
795
|
-
--api-key API_KEY API key for authentication. If not set, it tries to find it in env variable: MINI_CODE_API_KEY.
|
|
796
|
-
--cache-dir CACHE_DIR
|
|
797
|
-
The cache dir for the session histories. default=~/.cache/mini_code/sessions/
|
|
798
|
-
--restore-session RESTORE_SESSION
|
|
799
|
-
The location of a previous session to continue. (e.g. ~/.cache/mini_code/sessions/1792028090823027-a9d77653/)
|
|
800
|
-
--load-last-session Load the most recent previous session from the cache dir and continue it (under a new session id), instead of starting fresh. --restore-session takes precedence if also given.
|
|
801
|
-
--system-prompt SYSTEM_PROMPT
|
|
802
|
-
Replace system prompt, with a custom system prompt.
|
|
803
|
-
-a, --auto-mode Whether to run the agent in `auto-mode'. Or default: `manual-mode'.
|
|
804
|
-
--agent-md AGENT_MD If the agent should use an agent-md file... (it will added after system message.)
|
|
805
|
-
--prompt PROMPT An initial prompt from the user...
|
|
806
|
-
--ask-permission Ask for permission before any tool call. (Shell ALLOW-tier commands skip the prompt; DENY is blocked.)
|
|
807
|
-
--sudo DANGEROUS: never ask for permission. Every non-destructive tool call and shell command runs automatically without confirmation. Destructive (DENY-tier) commands are still refused.
|
|
808
|
-
--allowed-dir ALLOWED_DIR
|
|
809
|
-
Allowed directory for file operations, default='./'
|
|
810
|
-
-s, --enable-shell Allow shell execution. default= False
|
|
811
|
-
--enable-subagents Allow the agent to delegate work to sub-agents (exposed as extra tools). default= False
|
|
812
|
-
--llm-timeout LLM_TIMEOUT
|
|
813
|
-
HTTP timeout in seconds for LLM requests (reasoning models can be slow). default=500
|
|
814
|
-
--tool-timeout TOOL_TIMEOUT
|
|
815
|
-
Timeout in seconds for a single tool call. default=120
|
|
816
|
-
--plan Enable plan mode: the agent keeps a CURRENT_PLAN.md
|
|
817
|
-
(its step-by-step plan, marked finished when the goal
|
|
818
|
-
is done) and CURRENT_GOAL.md (the user's latest
|
|
819
|
-
instruction) in the session directory. Also changes
|
|
820
|
-
how history compaction works.
|
|
821
|
-
--verbose Print the full, detailed output. Without it (default),
|
|
822
|
-
only user/assistant turns, token usage and tool calls
|
|
823
|
-
are shown.
|
|
824
|
-
```
|
|
825
|
-
|
|
826
|
-
### In-session commands
|
|
827
884
|
|
|
828
|
-
|
|
829
|
-
/
|
|
830
|
-
|
|
831
|
-
/reset [<n>] rewind to the end of turn n (drops everything after it)
|
|
832
|
-
/clear clear the screen (keeps the conversation history)
|
|
833
|
-
/plan show the current goal + plan (plan mode only)
|
|
834
|
-
/help show this help
|
|
835
|
-
/quit, /exit save the session and exit
|
|
836
|
-
```
|
|
885
|
+
Releases are cut by tagging `main`: pushing a `v*` tag triggers
|
|
886
|
+
[`.github/workflows/release.yml`](.github/workflows/release.yml), which builds the sdist + wheel,
|
|
887
|
+
verifies them with `twine check`, and attaches them to a new GitHub release.
|
|
837
888
|
|
|
838
|
-
##
|
|
889
|
+
## Documentation
|
|
839
890
|
|
|
840
|
-
|
|
891
|
+
Everything beyond this README lives in [`docs/`](docs/):
|
|
841
892
|
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
893
|
+
| Document | What it covers |
|
|
894
|
+
| --- | --- |
|
|
895
|
+
| [**docs/README_DEV.md**](docs/README_DEV.md) | developer guide — local setup, repository layout, linting, the test suite, CI and the release / PyPI upload process |
|
|
896
|
+
| [**docs/ARCHITECTURE.md**](docs/ARCHITECTURE.md) | design — module layout, on-disk conversation state (`history_{n}.json`, `summary_history.json`, usage files), the sub-agent framework and how to extend it |
|
|
897
|
+
|
|
898
|
+
This README stays the user-facing entry point (install, CLI flags, tools, sub-agents,
|
|
899
|
+
in-session commands, modes & safety); the two documents above go deeper on the developer
|
|
900
|
+
and design side.
|
|
901
|
+
|
|
902
|
+
## Modes & safety
|
|
903
|
+
|
|
904
|
+
### Shell execution — `-s` / `--enable-shell`
|
|
905
|
+
|
|
906
|
+
Everything the agent runs from the shell first passes a **safety classifier** that sorts the
|
|
907
|
+
command into one of three tiers:
|
|
908
|
+
|
|
909
|
+
| Tier | Examples | What happens |
|
|
910
|
+
| --- | --- | --- |
|
|
911
|
+
| **DENY** | `rm -rf /`, `dd of=/dev/...`, `mkfs.*`, fork bombs | refused outright, never run |
|
|
912
|
+
| **ASK** | `rm file`, `sudo ...`, `chmod`, `curl ... \| sh` | requires your confirmation |
|
|
913
|
+
| **ALLOW** | `ls`, `cat`, `git status` | runs without prompting |
|
|
914
|
+
|
|
915
|
+
> [!WARNING]
|
|
916
|
+
> The classifier is **always enforced** — even in auto-mode and with `--sudo` — so the agent
|
|
917
|
+
> cannot run destructive commands unattended. It is a heuristic, not a sandbox: use it with care.
|
|
918
|
+
> `--allowed-dir` sandboxes **file tools**, not the shell.
|
|
919
|
+
|
|
920
|
+
### Plan mode — `-p` / `--plan`
|
|
921
|
+
|
|
922
|
+
The loop keeps two human-readable tracking files in the session directory: `CURRENT_GOAL.md`
|
|
923
|
+
(your latest instruction) and `CURRENT_PLAN.md` (a step-by-step plan for that goal, marked
|
|
924
|
+
finished when it is done). They are authored by the *loop*, not the agent, live outside
|
|
925
|
+
`--allowed-dir`, and can be inspected any time with `/plan`.
|
|
852
926
|
|
|
853
|
-
|
|
927
|
+
> [!NOTE]
|
|
928
|
+
> Plan mode also changes **history compaction**: after the transcript is compacted to a summary,
|
|
929
|
+
> `CURRENT_PLAN.md` and `CURRENT_GOAL.md` are re-injected, so the agent keeps working against the
|
|
930
|
+
> same goal. When the work looks done the plan is reviewed and any outstanding task is re-queued
|
|
931
|
+
> before the agent returns to you.
|
|
854
932
|
|
|
855
|
-
|
|
856
|
-
- **`test_tools.py`** — the tool functions. Confirms they *return* their results/errors (instead of printing), that `run_shell_command` captures stderr and honors a timeout, and that the generated tool schema exposes the expected parameters.
|
|
857
|
-
- **`test_agent_loop.py`** — agent-loop behaviour. Confirms that enabling the shell forces per-command permission prompts, that memory compaction is correctly wired (accepts token accounting), and that token-usage formatting handles servers that report no usage.
|
|
858
|
-
- **`test_shell_safety.py`** — the shell command classifier. Confirms commands are sorted into the three tiers correctly: destructive commands (`rm -rf /`, `dd of=/dev/...`, `mkfs.*`, fork bombs) are **DENY**, risky ones (`rm file`, `sudo`, `curl | sh`, redirects to `/etc/...`) are **ASK**, and safe ones (`ls`, `cat`, `git status`) are **ALLOW**.
|
|
933
|
+
### Sessions — resume, or start fresh
|
|
859
934
|
|
|
860
|
-
|
|
935
|
+
Every session is saved under `--cache-dir` (default `~/.cache/mini/sessions/`).
|
|
861
936
|
|
|
862
|
-
|
|
937
|
+
> [!TIP]
|
|
938
|
+
> If a previous session exists but you did **not** ask to resume one (neither
|
|
939
|
+
> `--load-last-session` nor `--restore-session`), the prompt offers **Resume / Start new / Exit**
|
|
940
|
+
> before the conversation begins. Ctrl-C or EOF there is a graceful exit. This is the *asking*
|
|
941
|
+
> variant; `--load-last-session` is the *silent* one.
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
| Flag | Behaviour |
|
|
945
|
+
| --- | --- |
|
|
946
|
+
| `--restore-session PATH` | continue that exact session (a session directory or a bare session id under `--cache-dir`) |
|
|
947
|
+
| `-l`, `--load-last-session` | continue the session recorded in the `.mini/last_session.json` pointer, without asking |
|
|
948
|
+
|
|
949
|
+
`--load-last-session` continues that session **in place** (same id, same folder, same
|
|
950
|
+
messages), so the conversation you were in is the one you get back; an explicit
|
|
951
|
+
`--restore-session` wins if both are given. The "most recent" session comes from a single
|
|
952
|
+
source — the tiny `.mini/last_session.json` pointer written when a session starts or is
|
|
953
|
+
restored inside `--allowed-dir` (deliberately no timestamp fallback: with no pointer, a fresh
|
|
954
|
+
session starts). That pointer lives in the same `.mini` directory as `--skills`, but as its
|
|
955
|
+
own dedicated file, so the two never clash.
|
|
956
|
+
|
|
957
|
+
A session folder is restorable only if it has what this version writes: a valid
|
|
958
|
+
`summary_history.json` recorder, plus the `history_{n}.json` segment its last record names
|
|
959
|
+
(usage files are optional). Anything else — a folder from an older release, a hand-assembled
|
|
960
|
+
transcript, a recorder that does not validate, a missing segment — is **refused with a note
|
|
961
|
+
saying why**, and a fresh session is started instead. Nothing is repaired, guessed at, or
|
|
962
|
+
written into the refused folder.
|
|
963
|
+
|
|
964
|
+
### Context compaction — `--max-context-tokens`
|
|
965
|
+
|
|
966
|
+
Compaction is decided by **tokens only**, never by message count: a few large tool outputs can
|
|
967
|
+
fill a window that hundreds of short turns would not. The next request is projected from the
|
|
968
|
+
server-reported `prompt_tokens`, plus an estimate of what was appended since, plus the output
|
|
969
|
+
reserve (`--max-tokens`). Unset (default) it is derived from the model's context window minus the
|
|
970
|
+
output reserve and a safety margin. Lower it to compact sooner, raise it to compact later — there
|
|
971
|
+
is no message-count cap to configure.
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
## Serving a model locally
|
|
975
|
+
|
|
976
|
+
Tested with vLLM v0.30 (tool calling enabled):
|
|
863
977
|
|
|
864
|
-
### Serving a vllm model locally (with correct tools). vllm v0.30 (tested):
|
|
865
978
|
```bash
|
|
866
979
|
vllm serve ornith-ai/Ornith-1.5-397B-FP8 \
|
|
867
980
|
--tensor-parallel-size 4 \
|
|
@@ -875,17 +988,19 @@ vllm serve ornith-ai/Ornith-1.5-397B-FP8 \
|
|
|
875
988
|
|
|
876
989
|
## Citation
|
|
877
990
|
|
|
878
|
-
If you use `mini-code-cli` in your research or writing, please cite it
|
|
991
|
+
If you use `mini-code-cli` in your research or writing, please cite it:
|
|
879
992
|
|
|
880
993
|
```bibtex
|
|
881
994
|
@misc{mini-code-cli,
|
|
882
995
|
author = {Rozanov, Nikolai},
|
|
883
996
|
title = {mini-code-cli: A minimal, dependency-light coding agent},
|
|
884
997
|
year = {2026},
|
|
885
|
-
version = {0.1.
|
|
998
|
+
version = {0.1.1.0},
|
|
886
999
|
howpublished = {\url{https://github.com/ai-nikolai/mini-code-cli}},
|
|
887
1000
|
note = {A no-bloat, dependency-free agent CLI for experimenting.}
|
|
888
1001
|
}
|
|
889
1002
|
```
|
|
890
1003
|
|
|
891
|
-
##
|
|
1004
|
+
## License
|
|
1005
|
+
|
|
1006
|
+
[AGPL-3.0](LICENSE) — (C) Nikolai Rozanov, 2026 – present.
|