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);dmrandllamacppare registry entries. - API keys are named by environment variable in YAML, never stored in it.
contextWindowis one top-level key shared by the banner and the compression trigger.- Documentation follows Diátaxis, bilingual:
docs/en/anddocs/fr/with identical file names;kits/andtmp/are out of scope. - Slash commands: terminal
/quit,/abort,/compact,/new; ACP/new,/compactonly (no/quit: the editor owns the process; no/abort: Escape in Zed cancels throughsession/cancel— user's decision 2026-09-15, an earlier/abortwas removed), advertised throughavailable_commands_updatesent right AFTER thesession/newresponse is written (a hook on the writer handed to the SDK,responseWriterininternal/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 whatsession/promptintercepts is advertised./newand/compactare intercepted underturnMu, so the history never moves under Genkit. The compaction report line iscompact.Result.Report(), shared by both front ends. /newresets 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/compactwhich keeps the detector. Over ACP it keeps the session id,cwdand "allow always" grants. Shared logic lives ininternal/session, imported ashistoryinsideinternal/acp(name clash with itssessionstruct).- Quality gate scope:
.qlty/qlty.tomlexcludeskits/**andtmp/**(user's request, 2026-09-15), drops qlty's default**/config/**exclusion sointernal/configis measured, and enablesgofmt,golangci-lint,osv-scannerby hand (qlty initonly saw tracked files, hence no Go). Do not re-runqlty init. - Zed
agent_serversentry for mm must carry"type": "custom"alongsidecommand/args/env; without it Zed rejects the entry (user report, 2026-09-15). Bothhow-to/use-from-an-editor.mdpages show the full block. - Skills: two layouts, flat
<name>.mdand<name>/SKILL.md(Agent Skills convention, the shipped one);Readprefers the flat file. A relativeskillsDiris made absolute inmain.go(resolveSkillsDir): from the current directory (terminal, or ACP without a config file) or next to the config file (ACP with one); the banner warnsno skills found in <abs path>when the count is 0. @pathmentions (internal/mention,Expand(input, cwd)): a typed@paththat 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 ACPresource_link— and is echoed (📎line in the terminal,[acp] … attachedon 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 fromgo 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/skillstest 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.").
.gitignoreexists. .tickets/(IssueSpec) holds three open issues: add a help command, add an about command, improve TUI.agent.yamlnames the agent "Bob" in its system prompt; ACPagentInfo.nameis alsobob, version0.11.0. The binary ismm.
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
-hwere exercised). - Whether the project wants
go.mod'sgo 1.25.0bumped 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 |
|