bots-garden/mini-mepublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/bots-garden/mini-me.git
git clone ssh://git@rickub.com/bots-garden/mini-me.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

💾 Saved. d722711 · on main · k33g · 2h ago
summary.md · 58 lines · 6.4 KBmarkdown
Blame HistoryOpen raw

mini-me (mm) — project summary

What it is

A minimal Go coding agent (module mm, Go 1.25 in go.mod, builds with Go 1.26.5) that drives a local LLM through the OpenAI-compatible chat-completions API with Genkit (github.com/firebase/genkit/go v1.10.0). Two front ends share one loop: a terminal REPL (internal/agent) and an Agent Client Protocol façade (internal/acp, github.com/coder/acp-go-sdk v0.13.5) selected with mm -acp.

Architecture (verified 2026-09-15)

main.go does the wiring only. Packages under internal/: config (defaults + YAML + AGENT_* env overrides), engine (provider registry dmr/llamacpp, streaming, watchdog, non-streaming retry, Summarize), tools (bash, read_skill, read_file, write_file, edit_file), fileedit (exact-replacement editing), skills (catalogue from <skillsDir>/*.md front matter), detector (repeated-action detection), compact (history compression), spinner, ui (Out writer + Sink event interface the ACP façade implements), agent, acp, session (added 2026-09-15 by the /new work — see history).

Commands

Purpose Command
Build go build -o mm .
Install ./install.sh (builds, copies to /usr/local/bin)
Test go test ./...
Run (DMR) ./mm (reads ./agent.yaml)
Run (llama.cpp) ./mm agent.llamacpp.yaml
Editor mm -acp with AGENT_CONFIG=<absolute path>
Quality gate python3 ~/.claude/skills/quality/scripts/quality_report.py --workspace . (report under .quality/, exit 0 = pass)

Use bash -l -c "…" in this sandbox so go is on the PATH.

Decisions in force

  • Tools return failures as text, never as Go errors (the model must read them).
  • Full history is kept after a failed/cancelled turn; only an unanswered question is dropped.
  • One provider type per wire protocol (openaiCompat); dmr and llamacpp are registry entries.
  • API keys are named by environment variable in YAML, never stored in it.
  • contextWindow is one top-level key shared by the banner and the compression trigger.
  • Documentation follows Diátaxis, bilingual: docs/en/ and docs/fr/ with identical file names; kits/ and tmp/ are out of scope.
  • Slash commands: terminal /quit, /abort, /compact, /new; ACP /new, /compact only (no /quit: the editor owns the process; no /abort: Escape in Zed cancels through session/cancel — user's decision 2026-09-15, an earlier /abort was removed), advertised through available_commands_update sent right AFTER the session/new response is written (a hook on the writer handed to the SDK, responseWriter in internal/acp/acp.go, fires when the response line carrying the session id goes out). Sending it before the response does not work: Zed drops updates for a session id it has not received yet (user report 2026-09-15; fix confirmed working in Zed by the user). Only what session/prompt intercepts is advertised. /new and /compact are intercepted under turnMu, so the history never moves under Genkit. The compaction report line is compact.Result.Report(), shared by both front ends.
  • /new resets the history (system prompt alone), the engine's last input-token count, and — terminal only — the loop detector (detector.Reset): a new session is a new task, unlike /compact which keeps the detector. Over ACP it keeps the session id, cwd and "allow always" grants. Shared logic lives in internal/session, imported as history inside internal/acp (name clash with its session struct).
  • Quality gate scope: .qlty/qlty.toml excludes kits/** and tmp/** (user's request, 2026-09-15), drops qlty's default **/config/** exclusion so internal/config is measured, and enables gofmt, golangci-lint, osv-scanner by hand (qlty init only saw tracked files, hence no Go). Do not re-run qlty init.
  • Zed agent_servers entry for mm must carry "type": "custom" alongside command/args/env; without it Zed rejects the entry (user report, 2026-09-15). Both how-to/use-from-an-editor.md pages show the full block.
  • Skills: two layouts, flat <name>.md and <name>/SKILL.md (Agent Skills convention, the shipped one); Read prefers the flat file. A relative skillsDir is made absolute in main.go (resolveSkillsDir): from the current directory (terminal, or ACP without a config file) or next to the config file (ACP with one); the banner warns no skills found in <abs path> when the count is 0.
  • @path mentions (internal/mention, Expand(input, cwd)): a typed @path that exists (relative to the start directory / session cwd, absolute, or ~/) appends [attached file: <abs>] / [attached directory: <abs>] to the message — the exact shape of an ACP resource_link — and is echoed (📎 line in the terminal, [acp] … attached on stderr). No picker, no completion, content never inlined; a non-existing path or a @ glued to a word is left alone. Used by both front ends.
  • The package import graph is kept in docs/diagrams/packages.drawio (generated from go list); update it when a package is added, removed or re-wired.

Known defects (verified 2026-09-15, not fixed)

  • None open. (The skills-layout bug and the demo/skills test path were fixed on 2026-09-15; go test ./... passes.)

Quality gate state (2026-09-15, 2 runs in .quality/history.jsonl)

FAIL on pre-existing debt only: 67 warnings (55 osv-scanner on go.mod — 47 against stdlib@1.25.0, i.e. the go directive, 8 against indirect deps jsonparser, otel, x/sys; 12 golangci-lint:errcheck in main.go, internal/engine, internal/fileedit) and 18 smells (complexity: agent.Run = 121, fileedit/diff.go, compact.Valid, engine.Generate, config.validate, engine.Explain). No finding in the /new code.

Repository oddities

  • Almost everything is untracked in git (only two commits, "Updated."). .gitignore exists.
  • .tickets/ (IssueSpec) holds three open issues: add a help command, add an about command, improve TUI.
  • agent.yaml names the agent "Bob" in its system prompt; ACP agentInfo.name is also bob, version 0.11.0. The binary is mm.

Not yet established

  • Whether a real DMR or llama-server run works end to end from this sandbox (no model server here; only the banner and -h were exercised).
  • Whether the project wants go.mod's go 1.25.0 bumped to 1.26 and the flagged indirect deps upgraded to clear the osv-scanner findings.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# mini-me (mm) — project summary

## What it is

A minimal Go coding agent (`module mm`, Go 1.25 in `go.mod`, builds with Go 1.26.5) that drives a local LLM through the OpenAI-compatible chat-completions API with Genkit (`github.com/firebase/genkit/go` v1.10.0). Two front ends share one loop: a terminal REPL (`internal/agent`) and an Agent Client Protocol façade (`internal/acp`, `github.com/coder/acp-go-sdk` v0.13.5) selected with `mm -acp`.

## Architecture (verified 2026-09-15)

`main.go` does the wiring only. Packages under `internal/`: `config` (defaults + YAML + `AGENT_*` env overrides), `engine` (provider registry `dmr`/`llamacpp`, streaming, watchdog, non-streaming retry, `Summarize`), `tools` (`bash`, `read_skill`, `read_file`, `write_file`, `edit_file`), `fileedit` (exact-replacement editing), `skills` (catalogue from `<skillsDir>/*.md` front matter), `detector` (repeated-action detection), `compact` (history compression), `spinner`, `ui` (`Out` writer + `Sink` event interface the ACP façade implements), `agent`, `acp`, `session` (added 2026-09-15 by the `/new` work — see history).

## Commands

| Purpose | Command |
|---------|---------|
| Build | `go build -o mm .` |
| Install | `./install.sh` (builds, copies to `/usr/local/bin`) |
| Test | `go test ./...` |
| Run (DMR) | `./mm` (reads `./agent.yaml`) |
| Run (llama.cpp) | `./mm agent.llamacpp.yaml` |
| Editor | `mm -acp` with `AGENT_CONFIG=<absolute path>` |
| Quality gate | `python3 ~/.claude/skills/quality/scripts/quality_report.py --workspace .` (report under `.quality/`, exit 0 = pass) |

Use `bash -l -c "…"` in this sandbox so `go` is on the PATH.

## Decisions in force

- Tools return failures as text, never as Go errors (the model must read them).
- Full history is kept after a failed/cancelled turn; only an unanswered question is dropped.
- One provider type per wire protocol (`openaiCompat`); `dmr` and `llamacpp` are registry entries.
- API keys are named by environment variable in YAML, never stored in it.
- `contextWindow` is one top-level key shared by the banner and the compression trigger.
- Documentation follows Diátaxis, bilingual: `docs/en/` and `docs/fr/` with identical file names; `kits/` and `tmp/` are out of scope.
- Slash commands: terminal `/quit`, `/abort`, `/compact`, `/new`; ACP `/new`, `/compact` only (no `/quit`: the editor owns the process; no `/abort`: Escape in Zed cancels through `session/cancel` — user's decision 2026-09-15, an earlier `/abort` was removed), advertised through `available_commands_update` sent right AFTER the `session/new` response is written (a hook on the writer handed to the SDK, `responseWriter` in `internal/acp/acp.go`, fires when the response line carrying the session id goes out). Sending it before the response does not work: Zed drops updates for a session id it has not received yet (user report 2026-09-15; fix confirmed working in Zed by the user). Only what `session/prompt` intercepts is advertised. `/new` and `/compact` are intercepted under `turnMu`, so the history never moves under Genkit. The compaction report line is `compact.Result.Report()`, shared by both front ends.
- `/new` resets the history (system prompt alone), the engine's last input-token count, and — terminal only — the loop detector (`detector.Reset`): a new session is a new task, unlike `/compact` which keeps the detector. Over ACP it keeps the session id, `cwd` and "allow always" grants. Shared logic lives in `internal/session`, imported as `history` inside `internal/acp` (name clash with its `session` struct).
- Quality gate scope: `.qlty/qlty.toml` excludes `kits/**` and `tmp/**` (user's request, 2026-09-15), drops qlty's default `**/config/**` exclusion so `internal/config` is measured, and enables `gofmt`, `golangci-lint`, `osv-scanner` by hand (`qlty init` only saw tracked files, hence no Go). Do not re-run `qlty init`.
- Zed `agent_servers` entry for mm must carry `"type": "custom"` alongside `command`/`args`/`env`; without it Zed rejects the entry (user report, 2026-09-15). Both `how-to/use-from-an-editor.md` pages show the full block.
- Skills: two layouts, flat `<name>.md` and `<name>/SKILL.md` (Agent Skills convention, the shipped one); `Read` prefers the flat file. A relative `skillsDir` is made absolute in `main.go` (`resolveSkillsDir`): from the current directory (terminal, or ACP without a config file) or next to the config file (ACP with one); the banner warns `no skills found in <abs path>` when the count is 0.
- `@path` mentions (`internal/mention`, `Expand(input, cwd)`): a typed `@path` that exists (relative to the start directory / session cwd, absolute, or `~/`) appends `[attached file: <abs>]` / `[attached directory: <abs>]` to the message — the exact shape of an ACP `resource_link` — and is echoed (`📎` line in the terminal, `[acp] … attached` on stderr). No picker, no completion, content never inlined; a non-existing path or a `@` glued to a word is left alone. Used by both front ends.
- The package import graph is kept in `docs/diagrams/packages.drawio` (generated from `go list`); update it when a package is added, removed or re-wired.

## Known defects (verified 2026-09-15, not fixed)

- None open. (The skills-layout bug and the `demo/skills` test path were fixed on 2026-09-15; `go test ./...` passes.)

## Quality gate state (2026-09-15, 2 runs in `.quality/history.jsonl`)

FAIL on pre-existing debt only: 67 warnings (55 `osv-scanner` on `go.mod` — 47 against `stdlib@1.25.0`, i.e. the `go` directive, 8 against indirect deps `jsonparser`, `otel`, `x/sys`; 12 `golangci-lint:errcheck` in `main.go`, `internal/engine`, `internal/fileedit`) and 18 smells (complexity: `agent.Run` = 121, `fileedit/diff.go`, `compact.Valid`, `engine.Generate`, `config.validate`, `engine.Explain`). No finding in the `/new` code.

## Repository oddities

- Almost everything is untracked in git (only two commits, "Updated."). `.gitignore` exists.
- `.tickets/` (IssueSpec) holds three open issues: add a help command, add an about command, improve TUI.
- `agent.yaml` names the agent "Bob" in its system prompt; ACP `agentInfo.name` is also `bob`, version `0.11.0`. The binary is `mm`.

## Not yet established

- Whether a real DMR or llama-server run works end to end from this sandbox (no model server here; only the banner and `-h` were exercised).
- Whether the project wants `go.mod`'s `go 1.25.0` bumped to 1.26 and the flagged indirect deps upgraded to clear the osv-scanner findings.