bots-garden/mini-me-kitpublic Fork
⑂ 7a9dc8f
Commits
⬇ Clone ▾
git clone https://git.rickub.com/bots-garden/mini-me-kit.git
git clone ssh://git@rickub.com/bots-garden/mini-me-kit.git

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

🛟 Updated.Unverified

k33g committed 2026-10-10T06:37:06+02:00 Browse files
7a9dc8f
added .github/workflows/release.yml +47 -0
new file mode 100644
@@ -0,0 +1,47 @@
1+name: Release
2+
3+# Publishes a release with the cross-compiled binaries whenever a tag v* is
4+# pushed — what ./01-release.tag.sh does at its last line. The binaries are
5+# built by ./02-build-releases.sh, the same script one runs on a laptop, so a
6+# local build and a published one are byte-for-byte the same pipeline.
7+#
8+# Rickub runs this as an ordinary GitHub Actions workflow. Two platform facts
9+# matter here: the job's GITHUB_TOKEN is the ONLY credential the release API
10+# (the /gh shim behind $GITHUB_API_URL) accepts — a personal token is refused —
11+# and it is read-only unless the workflow asks for `contents: write` below.
12+#
13+# No workflow_dispatch on purpose: Rickub's dispatch API fires EVERY
14+# dispatchable workflow of a ref, so a repository should declare at most one.
15+on:
16+ push:
17+ tags:
18+ - "v*"
19+
20+permissions:
21+ contents: write
22+
23+concurrency:
24+ group: release-${{ github.ref_name }}
25+ cancel-in-progress: false
26+
27+jobs:
28+ release:
29+ name: build and publish ${{ github.ref_name }}
30+ runs-on: ubuntu-latest
31+ steps:
32+ - name: Checkout
33+ uses: actions/checkout@v4
34+ with:
35+ # The whole history and the tags: the release notes below are read
36+ # from the annotated tag's message.
37+ fetch-depth: 0
38+
39+ - name: Publish the release
40+ uses: softprops/action-gh-release@v2
41+ with:
42+ tag_name: ${{ github.ref_name }}
43+ name: ${{ github.ref_name }}
44+ body_path: ${{ steps.notes.outputs.path }}
45+ draft: false
46+ prerelease: ${{ contains(github.ref_name, '-') }}
47+
new file mode 100644
@@ -0,0 +1,47 @@
1+name: Release
2+
3+# Publishes a release with the cross-compiled binaries whenever a tag v* is
4+# pushed — what ./01-release.tag.sh does at its last line. The binaries are
5+# built by ./02-build-releases.sh, the same script one runs on a laptop, so a
6+# local build and a published one are byte-for-byte the same pipeline.
7+#
8+# Rickub runs this as an ordinary GitHub Actions workflow. Two platform facts
9+# matter here: the job's GITHUB_TOKEN is the ONLY credential the release API
10+# (the /gh shim behind $GITHUB_API_URL) accepts — a personal token is refused —
11+# and it is read-only unless the workflow asks for `contents: write` below.
12+#
13+# No workflow_dispatch on purpose: Rickub's dispatch API fires EVERY
14+# dispatchable workflow of a ref, so a repository should declare at most one.
15+on:
16+ push:
17+ tags:
18+ - "v*"
19+
20+permissions:
21+ contents: write
22+
23+concurrency:
24+ group: release-${{ github.ref_name }}
25+ cancel-in-progress: false
26+
27+jobs:
28+ release:
29+ name: build and publish ${{ github.ref_name }}
30+ runs-on: ubuntu-latest
31+ steps:
32+ - name: Checkout
33+ uses: actions/checkout@v4
34+ with:
35+ # The whole history and the tags: the release notes below are read
36+ # from the annotated tag's message.
37+ fetch-depth: 0
38+
39+ - name: Publish the release
40+ uses: softprops/action-gh-release@v2
41+ with:
42+ tag_name: ${{ github.ref_name }}
43+ name: ${{ github.ref_name }}
44+ body_path: ${{ steps.notes.outputs.path }}
45+ draft: false
46+ prerelease: ${{ contains(github.ref_name, '-') }}
47+
added .gitignore +0 -0
new file mode 100644
new file mode 100644
added .vscode/extensions.json +9 -0
new file mode 100644
@@ -0,0 +1,9 @@
1+{
2+ "recommendations": [
3+ "ms-azuretools.vscode-docker",
4+ "pkief.material-icon-theme",
5+ "pkief.material-product-icons",
6+ "aaron-bond.better-comments",
7+ "bierner.markdown-mermaid",
8+ ]
9+}
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,9 @@
1+{
2+ "recommendations": [
3+ "ms-azuretools.vscode-docker",
4+ "pkief.material-icon-theme",
5+ "pkief.material-product-icons",
6+ "aaron-bond.better-comments",
7+ "bierner.markdown-mermaid",
8+ ]
9+}
\ No newline at end of file\ No newline at end of file
added .vscode/settings.json +63 -0
new file mode 100644
@@ -0,0 +1,63 @@
1+{
2+ "workbench.iconTheme": "material-icon-theme",
3+ "workbench.colorTheme": "Light Modern",
4+ "editor.fontSize": 14,
5+ "terminal.integrated.fontSize": 16,
6+ "editor.insertSpaces": true,
7+ "editor.tabSize": 4,
8+ "editor.detectIndentation": true,
9+ "files.autoSave": "afterDelay",
10+ "files.autoSaveDelay": 1000,
11+ // "editor.defaultFormatter": "esbenp.prettier-vscode",
12+ "editor.formatOnSave": true,
13+ "workbench.tree.indent": 20,
14+ //"workbench.activityBar.location": "top",
15+ "workbench.editor.showTabs": "multiple",
16+ "window.zoomLevel": 0.0,
17+ "[markdown]": {
18+ "editor.unicodeHighlight.ambiguousCharacters": false,
19+ "editor.unicodeHighlight.invisibleCharacters": false,
20+ "diffEditor.ignoreTrimWhitespace": false,
21+ "editor.fontWeight": "normal",
22+ "editor.fontFamily": "'Droid Sans Mono', 'monospace', monospace",
23+ "editor.fontSize": 14,
24+ "editor.wordWrap": "on",
25+ "editor.quickSuggestions": {
26+ "comments": "off",
27+ "strings": "off",
28+ "other": "off"
29+ }
30+ },
31+ "markdown.preview.fontSize": 14,
32+ // "workbench.editorAssociations": {
33+ // "*.md": "vscode.markdown.preview.editor"
34+ // },
35+ "markdown.marp.html": "all",
36+ "[dockerfile]": {
37+ "editor.fontSize": 14
38+ },
39+ "[dockercompose]": {
40+ "editor.fontSize": 14
41+ },
42+ "[json]": {
43+ "editor.fontSize": 14
44+ },
45+ "[yaml]": {
46+ "editor.fontSize": 14
47+ },
48+ "[go]": {
49+ "editor.fontSize": 14,
50+ "editor.codeActionsOnSave": {
51+ "source.organizeImports": "explicit"
52+ }
53+ },
54+ "go.lintTool": "golangci-lint",
55+ "go.lintOnSave": "package",
56+ "go.formatTool": "goimports",
57+ "go.useLanguageServer": true,
58+ "gopls": {
59+ "ui.semanticTokens": true,
60+ "ui.completion.usePlaceholders": true
61+ },
62+ "issuespec.groupBy": "milestone"
63+}
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,63 @@
1+{
2+ "workbench.iconTheme": "material-icon-theme",
3+ "workbench.colorTheme": "Light Modern",
4+ "editor.fontSize": 14,
5+ "terminal.integrated.fontSize": 16,
6+ "editor.insertSpaces": true,
7+ "editor.tabSize": 4,
8+ "editor.detectIndentation": true,
9+ "files.autoSave": "afterDelay",
10+ "files.autoSaveDelay": 1000,
11+ // "editor.defaultFormatter": "esbenp.prettier-vscode",
12+ "editor.formatOnSave": true,
13+ "workbench.tree.indent": 20,
14+ //"workbench.activityBar.location": "top",
15+ "workbench.editor.showTabs": "multiple",
16+ "window.zoomLevel": 0.0,
17+ "[markdown]": {
18+ "editor.unicodeHighlight.ambiguousCharacters": false,
19+ "editor.unicodeHighlight.invisibleCharacters": false,
20+ "diffEditor.ignoreTrimWhitespace": false,
21+ "editor.fontWeight": "normal",
22+ "editor.fontFamily": "'Droid Sans Mono', 'monospace', monospace",
23+ "editor.fontSize": 14,
24+ "editor.wordWrap": "on",
25+ "editor.quickSuggestions": {
26+ "comments": "off",
27+ "strings": "off",
28+ "other": "off"
29+ }
30+ },
31+ "markdown.preview.fontSize": 14,
32+ // "workbench.editorAssociations": {
33+ // "*.md": "vscode.markdown.preview.editor"
34+ // },
35+ "markdown.marp.html": "all",
36+ "[dockerfile]": {
37+ "editor.fontSize": 14
38+ },
39+ "[dockercompose]": {
40+ "editor.fontSize": 14
41+ },
42+ "[json]": {
43+ "editor.fontSize": 14
44+ },
45+ "[yaml]": {
46+ "editor.fontSize": 14
47+ },
48+ "[go]": {
49+ "editor.fontSize": 14,
50+ "editor.codeActionsOnSave": {
51+ "source.organizeImports": "explicit"
52+ }
53+ },
54+ "go.lintTool": "golangci-lint",
55+ "go.lintOnSave": "package",
56+ "go.formatTool": "goimports",
57+ "go.useLanguageServer": true,
58+ "gopls": {
59+ "ui.semanticTokens": true,
60+ "ui.completion.usePlaceholders": true
61+ },
62+ "issuespec.groupBy": "milestone"
63+}
\ No newline at end of file\ No newline at end of file
added 01-release.tag.sh +68 -0
new file mode 100755
@@ -0,0 +1,68 @@
1+#!/bin/bash
2+: <<'COMMENT'
3+1. Update TAG and ABOUT in release.env
4+2. Run this script: ./01-release.tag.sh (commit, push, tag, push the tag)
5+3. Watch the "Release" workflow on Rickub (Actions tab): the tag push starts
6+ it; it builds the binaries with ./02-build-releases.sh and publishes the
7+ release with them, using the job's own token. No personal token is needed.
8+COMMENT
9+
10+# Without this, a failing step is ignored and the next one runs anyway. That is
11+# not theoretical: `git tag` refusing a tag that already existed was skipped in
12+# silence, and the `git push` below then pushed the OLD tag — so a release was
13+# cut from a commit nobody meant, and 03 was left to notice.
14+set -euo pipefail
15+
16+set -o allexport
17+source release.env
18+set +o allexport
19+
20+echo "Generating release: ${TAG} ${ABOUT}"
21+
22+# tagExists reports whether TAG is already taken, here or on the remote. The
23+# remote matters on its own: a tag deleted locally after a failed attempt still
24+# exists there, and pushing a new one at a different commit is rejected.
25+tagExists() {
26+ if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
27+ printf 'locally, on %s\n' "$(git rev-parse --short "${TAG}^{commit}")"
28+ return 0
29+ fi
30+ if ! remote="$(git ls-remote --tags origin "refs/tags/${TAG}" 2>/dev/null)"; then
31+ return 1 # the remote is unreachable; the push below will say so
32+ fi
33+ if [ -n "${remote}" ]; then
34+ # No commit is named here on purpose: for an annotated tag ls-remote
35+ # gives the tag object, not the commit, and printing that as if it were
36+ # the commit sends the reader looking for a SHA they will never find.
37+ printf 'on origin\n'
38+ return 0
39+ fi
40+ return 1
41+}
42+
43+if where="$(tagExists)"; then
44+ echo "❌ ${TAG} already exists ${where}"
45+ echo "💡 Bump TAG in release.env, or move the tag onto this commit:"
46+ echo " git tag -f -a ${TAG} -m \"${ABOUT}\""
47+ echo " git push --force origin ${TAG}"
48+ exit 1
49+fi
50+
51+find . -name '.DS_Store' -type f -delete
52+
53+git add .
54+
55+# Nothing to commit is not a failure — the work may already be committed — but
56+# under `set -e` a plain `git commit` would stop the release right here.
57+if git diff --cached --quiet; then
58+ echo "Nothing to commit; releasing what is already on HEAD"
59+else
60+ git commit -m "📦 ${ABOUT}"
61+fi
62+
63+git push origin main
64+
65+# The tag goes on after the push, so a rejected push never leaves a tag behind
66+# pointing at a commit the remote has never seen.
67+git tag -a "${TAG}" -m "${ABOUT}"
68+git push origin "${TAG}"
new file mode 100755
@@ -0,0 +1,68 @@
1+#!/bin/bash
2+: <<'COMMENT'
3+1. Update TAG and ABOUT in release.env
4+2. Run this script: ./01-release.tag.sh (commit, push, tag, push the tag)
5+3. Watch the "Release" workflow on Rickub (Actions tab): the tag push starts
6+ it; it builds the binaries with ./02-build-releases.sh and publishes the
7+ release with them, using the job's own token. No personal token is needed.
8+COMMENT
9+
10+# Without this, a failing step is ignored and the next one runs anyway. That is
11+# not theoretical: `git tag` refusing a tag that already existed was skipped in
12+# silence, and the `git push` below then pushed the OLD tag — so a release was
13+# cut from a commit nobody meant, and 03 was left to notice.
14+set -euo pipefail
15+
16+set -o allexport
17+source release.env
18+set +o allexport
19+
20+echo "Generating release: ${TAG} ${ABOUT}"
21+
22+# tagExists reports whether TAG is already taken, here or on the remote. The
23+# remote matters on its own: a tag deleted locally after a failed attempt still
24+# exists there, and pushing a new one at a different commit is rejected.
25+tagExists() {
26+ if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null; then
27+ printf 'locally, on %s\n' "$(git rev-parse --short "${TAG}^{commit}")"
28+ return 0
29+ fi
30+ if ! remote="$(git ls-remote --tags origin "refs/tags/${TAG}" 2>/dev/null)"; then
31+ return 1 # the remote is unreachable; the push below will say so
32+ fi
33+ if [ -n "${remote}" ]; then
34+ # No commit is named here on purpose: for an annotated tag ls-remote
35+ # gives the tag object, not the commit, and printing that as if it were
36+ # the commit sends the reader looking for a SHA they will never find.
37+ printf 'on origin\n'
38+ return 0
39+ fi
40+ return 1
41+}
42+
43+if where="$(tagExists)"; then
44+ echo "❌ ${TAG} already exists ${where}"
45+ echo "💡 Bump TAG in release.env, or move the tag onto this commit:"
46+ echo " git tag -f -a ${TAG} -m \"${ABOUT}\""
47+ echo " git push --force origin ${TAG}"
48+ exit 1
49+fi
50+
51+find . -name '.DS_Store' -type f -delete
52+
53+git add .
54+
55+# Nothing to commit is not a failure — the work may already be committed — but
56+# under `set -e` a plain `git commit` would stop the release right here.
57+if git diff --cached --quiet; then
58+ echo "Nothing to commit; releasing what is already on HEAD"
59+else
60+ git commit -m "📦 ${ABOUT}"
61+fi
62+
63+git push origin main
64+
65+# The tag goes on after the push, so a rejected push never leaves a tag behind
66+# pointing at a commit the remote has never seen.
67+git tag -a "${TAG}" -m "${ABOUT}"
68+git push origin "${TAG}"
added README.md +13 -0
new file mode 100644
@@ -0,0 +1,13 @@
1+# Mini Me sbx kit
2+
3+> `agent.yaml` is the default config file name
4+```bash
5+cd demo
6+sbx run --name mm-demo ../mini-me
7+```
8+
9+> Use another config file name
10+```bash
11+cd demo
12+sbx run --name mm-demo ../mini-me -- -tui -config agent.lucy.yaml
13+```
new file mode 100644
@@ -0,0 +1,13 @@
1+# Mini Me sbx kit
2+
3+> `agent.yaml` is the default config file name
4+```bash
5+cd demo
6+sbx run --name mm-demo ../mini-me
7+```
8+
9+> Use another config file name
10+```bash
11+cd demo
12+sbx run --name mm-demo ../mini-me -- -tui -config agent.lucy.yaml
13+```
added demo/AGENTS.md +7 -0
new file mode 100644
@@ -0,0 +1,7 @@
1+# AGENTS.md
2+
3+## Mini Me sandbox
4+
5+You are running inside a Docker sandbox. The project is mounted as the
6+workspace; run commands from its root. Network access is restricted: if a
7+download fails, report the blocked host instead of retrying.
new file mode 100644
@@ -0,0 +1,7 @@
1+# AGENTS.md
2+
3+## Mini Me sandbox
4+
5+You are running inside a Docker sandbox. The project is mounted as the
6+workspace; run commands from its root. Network access is restricted: if a
7+download fails, report the blocked host instead of retrying.
added demo/agent.lucy.yaml +210 -0
new file mode 100644
@@ -0,0 +1,210 @@
1+# Agent settings — Lucy: mini-me on hf.co/Menlo/Lucy-gguf:Q4_K_M, served by llmman (https://github.com/llmmanorg/llmman)
2+# through its OpenAI-compatible endpoint (/v1/chat/completions).
3+#
4+# llmman pull hf.co/Menlo/Lucy-gguf:Q4_K_M # optional: the first question pulls it otherwise
5+# llmman serve # 127.0.0.1:17434
6+#
7+# llmman loads the model on the first request (in its own llama-server) and
8+# unloads it after five idle minutes.
9+provider: llmman
10+
11+# The model id exactly as `llmman list` / GET /v1/models spells it.
12+model: hf.co/Menlo/Lucy-gguf:Q4_K_M
13+
14+# `llmman serve`'s default bind; the OpenAI routes sit under /v1.
15+baseUrl: http://127.0.0.1:17434/v1
16+
17+# From a Docker sandbox, the daemon runs on the host.
18+fallback: http://host.docker.internal:17434/v1
19+
20+# Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it
21+# listens beyond loopback); unset otherwise. The key never goes in this file.
22+# apiKeyEnv: LLMMAN_API_KEY
23+
24+# Yolo mode. `true` (default): the tools run without asking.
25+# `false`: every bash call, file write/edit, fetch_content save, lsp rename and plan change
26+# waits for your answer — [a] once, [s] for the session, [r] reject, [n] never — in the
27+# terminal, the window and the editor; MCP tools ask too.
28+# bashTool / editTools still decide which tools EXIST. Called through /ask (mmConfigs),
29+# an agent follows its asker's yolo, not this one. Override for one run: AGENT_YOLO=false.
30+yolo: true
31+
32+# The `bash` tool.
33+# `false` removes it: the model can still read and edit files (editTools) and load skills,
34+# but never runs a command. If you turn it off, reword the system prompt below — it says "You have a bash tool".
35+bashTool: true
36+
37+# The built-in file tools: read_file, write_file, edit_file.
38+editTools: true
39+
40+# The built-in plan tool for managing multi-step plans.
41+# Set to false to disable plan creation and tracking via the `plan` tool.
42+planTool: true
43+
44+# Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename).
45+# The file extension picks the server. A server missing from the PATH is skipped with a warning.
46+# No server listed = no `lsp` tool. Examples (uncomment what you have installed):
47+# lsp:
48+# servers:
49+# - name: gopls
50+# command: gopls
51+# extensions: [".go"]
52+# - name: typescript
53+# command: typescript-language-server
54+# args: ["--stdio"]
55+# extensions: [".ts", ".tsx", ".js", ".jsx"]
56+# - name: python
57+# command: pyright-langserver
58+# args: ["--stdio"]
59+# extensions: [".py"]
60+# - name: rust
61+# command: rust-analyzer
62+# extensions: [".rs"]
63+
64+# How many tokens the server actually serves.
65+# 0 = ask llmman: /api/ps tells it once the model is loaded, so the window is
66+# learned before the second question. Set it here if you want it from the start
67+# — and to the same value as LLMMAN_CONTEXT_LENGTH if you set that variable.
68+contextWindow: 0
69+
70+# Max number of characters a tool returns to the model.
71+# Context safeguard: beyond that, the output is truncated (beginning + end kept).
72+maxOutput: 16000
73+
74+# Max number of model <-> tools round trips for a single question.
75+# Raise it for tasks that need long chains of commands.
76+maxTurns: 40
77+
78+# Where the `read_skill` tool looks for its markdown procedures.
79+# The path is relative to the CURRENT DIRECTORY: run the agent from sbx/.
80+skillsDir: ../skills
81+
82+# Persistent sessions, per project.
83+# When enabled, every conversation is saved as one JSON file under `dir`.
84+# `/sessions` lists them, `/resume` continues one; in an editor, "Reload Agent" replays the thread.
85+sessions:
86+ enabled: true
87+ dir: .mm/sessions
88+
89+# How many lines of a command's output are echoed to the terminal.
90+# 0 disables it.
91+previewLines: 20
92+
93+displayCommands: true
94+# Show what a thinking model reasons about before it answers (dim italic in the
95+# terminal, its own style in the window, a thought chunk in an editor).
96+# The reasoning is always READ — it is what keeps the watchdog alive while the
97+# model thinks — this only says whether to show it.
98+showThinking: true
99+
100+acp:
101+ name: lucy
102+ title: Lucy (coding agent)
103+
104+# The system prompt: what the agent is, and what it is allowed to do.
105+# This is the knob to play with — it is the shortest path to changing behaviour.
106+system: |
107+ Your name is Lucy.
108+ You are a coding agent working in a terminal.
109+ You have a "bash" tool to run shell commands.
110+ Use it to explore files, run tests, inspect the repository, etc.
111+ Chain several commands if needed, then answer clearly in English.
112+
113+ A request often mixes things you answer from yourself ("say hello") with
114+ things only a command can answer ("list the files"). Handle every part, in
115+ the order asked, and run a command for each part that needs one.
116+ Never state the contents of a file, the output of a command, or the state of
117+ the repository unless a command in THIS answer returned it. What you did not
118+ read, you do not know: run the command instead of recalling it.
119+
120+ SKILLS
121+ You have a second tool, `read_skill`. Its description lists the procedures
122+ available for this project — one per kind of task.
123+
124+ Any request to DO something to a Go project is a skill, not a shell command
125+ you invent. Match the request against that list, call `read_skill` FIRST,
126+ before any bash command, and then follow what it says step by step.
127+
128+ FILE EDITING
129+ You have three tools for files: `read_file`, `edit_file` and `write_file`.
130+ They are how a file gets read and changed here: each change is exact,
131+ checked before it is written, and comes back as a diff with line numbers.
132+ bash is for running things — building, testing, listing, searching.
133+
134+ - Read before you write: call `read_file` on the file (numbered=true when
135+ you need line numbers). You cannot target text you have not seen; never
136+ rely on what you think you remember about a file.
137+ - To change an existing file, call `edit_file` with one or more {old, new}
138+ pairs. `old` is copied from the file character for character — same
139+ spaces, same indentation, same line breaks — and appears exactly once:
140+ add the surrounding lines until it is unique. Several pairs are applied
141+ together, against the original file. An empty `new` deletes the text.
142+ - Call `write_file` only to create a file, or to rewrite one entirely and
143+ on purpose. On an existing file it replaces everything, including what
144+ you did not intend to touch.
145+ - Read the diff the tool returns: it says exactly what changed and on which
146+ line. If `edit_file` refuses — text not found, ambiguous, overlapping
147+ edits — read the file again and fix `old`. Do not fall back to
148+ `write_file` to force the change through.
149+ - After editing code, run the narrowest check with bash: the formatter, the
150+ compiler, or the test covering that file.
151+
152+ RULES
153+ - Keep everything the file already does, unless the user asked to remove it.
154+ - Touch only the files the request is about. Do not add tests, files or
155+ features that were not asked for.
156+ - Never run a git command unless the user says git, commit or push.
157+ - Never move, rename or delete a file unless the user asked for it.
158+ - Then answer in English, in a few lines.
159+ - If you don't know how to use a <cli>, run `<cli> --help` (or `<cli> help`)
160+ to understand the options, then run the command.
161+
162+ BACKGROUND JOBS
163+ Never let a command block the answer. Anything that serves, watches or runs
164+ long goes to the background, with BOTH streams redirected and its pid kept:
165+
166+ nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid
167+
168+ Redirecting only stdout still blocks until the process exits. Read the
169+ `bg-jobs` skill before you wait on, inspect or stop such a job — each has a
170+ rule you cannot guess. Stop every job you started before you finish, and say
171+ which ones you left running.
172+
173+# Generation settings (OpenAI API keys). Low temperature for a coding agent:
174+# we want precise and reproducible answers, not creativity.
175+sampling:
176+ temperature: 0.0
177+ parallel_tool_calls: false
178+ top_p: 0.9
179+ max_tokens: 4096
180+
181+# Silence allowed between two tokens once the answer has started.
182+watchdogTimeout: 30s
183+
184+# Silence allowed while the model reads the prompt, before the first token:
185+# on a laptop a 25k-token prompt can take minutes. llama-server reports its
186+# progress meanwhile, through llmman ("Reading the prompt 12.0k/25.3k tokens"), and each report
187+# restarts this clock, so it only has to cover one batch of the prompt.
188+firstTokenTimeout: 3m
189+
190+# Context compression.
191+# ON here: the agent learns the window from /api/ps, so `threshold` has a number to apply to.
192+context:
193+ enabled: true
194+
195+ # Compress when the history reaches this share of the window.
196+ threshold: 75
197+
198+ # Fallback on the message count, for when the window is unknown.
199+ # One command costs 2 messages (call + response), so 80 is roughly 30 commands of history.
200+ maxMessages: 80
201+
202+ # How many recent questions (with their commands and answers) are kept as-is instead of being summarised.
203+ # The model works on the last few turns, so summarising them would make it redo what it just did.
204+ keepLastTurns: 3
205+
206+ # max_tokens of the summary request. Reasoning is turned off for it on this provider
207+ # (a thinking model would otherwise spend the budget thinking and write nothing).
208+ summaryMaxTokens: 1200
209+
210+ showStats: true
new file mode 100644
@@ -0,0 +1,210 @@
1+# Agent settings — Lucy: mini-me on hf.co/Menlo/Lucy-gguf:Q4_K_M, served by llmman (https://github.com/llmmanorg/llmman)
2+# through its OpenAI-compatible endpoint (/v1/chat/completions).
3+#
4+# llmman pull hf.co/Menlo/Lucy-gguf:Q4_K_M # optional: the first question pulls it otherwise
5+# llmman serve # 127.0.0.1:17434
6+#
7+# llmman loads the model on the first request (in its own llama-server) and
8+# unloads it after five idle minutes.
9+provider: llmman
10+
11+# The model id exactly as `llmman list` / GET /v1/models spells it.
12+model: hf.co/Menlo/Lucy-gguf:Q4_K_M
13+
14+# `llmman serve`'s default bind; the OpenAI routes sit under /v1.
15+baseUrl: http://127.0.0.1:17434/v1
16+
17+# From a Docker sandbox, the daemon runs on the host.
18+fallback: http://host.docker.internal:17434/v1
19+
20+# Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it
21+# listens beyond loopback); unset otherwise. The key never goes in this file.
22+# apiKeyEnv: LLMMAN_API_KEY
23+
24+# Yolo mode. `true` (default): the tools run without asking.
25+# `false`: every bash call, file write/edit, fetch_content save, lsp rename and plan change
26+# waits for your answer — [a] once, [s] for the session, [r] reject, [n] never — in the
27+# terminal, the window and the editor; MCP tools ask too.
28+# bashTool / editTools still decide which tools EXIST. Called through /ask (mmConfigs),
29+# an agent follows its asker's yolo, not this one. Override for one run: AGENT_YOLO=false.
30+yolo: true
31+
32+# The `bash` tool.
33+# `false` removes it: the model can still read and edit files (editTools) and load skills,
34+# but never runs a command. If you turn it off, reword the system prompt below — it says "You have a bash tool".
35+bashTool: true
36+
37+# The built-in file tools: read_file, write_file, edit_file.
38+editTools: true
39+
40+# The built-in plan tool for managing multi-step plans.
41+# Set to false to disable plan creation and tracking via the `plan` tool.
42+planTool: true
43+
44+# Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename).
45+# The file extension picks the server. A server missing from the PATH is skipped with a warning.
46+# No server listed = no `lsp` tool. Examples (uncomment what you have installed):
47+# lsp:
48+# servers:
49+# - name: gopls
50+# command: gopls
51+# extensions: [".go"]
52+# - name: typescript
53+# command: typescript-language-server
54+# args: ["--stdio"]
55+# extensions: [".ts", ".tsx", ".js", ".jsx"]
56+# - name: python
57+# command: pyright-langserver
58+# args: ["--stdio"]
59+# extensions: [".py"]
60+# - name: rust
61+# command: rust-analyzer
62+# extensions: [".rs"]
63+
64+# How many tokens the server actually serves.
65+# 0 = ask llmman: /api/ps tells it once the model is loaded, so the window is
66+# learned before the second question. Set it here if you want it from the start
67+# — and to the same value as LLMMAN_CONTEXT_LENGTH if you set that variable.
68+contextWindow: 0
69+
70+# Max number of characters a tool returns to the model.
71+# Context safeguard: beyond that, the output is truncated (beginning + end kept).
72+maxOutput: 16000
73+
74+# Max number of model <-> tools round trips for a single question.
75+# Raise it for tasks that need long chains of commands.
76+maxTurns: 40
77+
78+# Where the `read_skill` tool looks for its markdown procedures.
79+# The path is relative to the CURRENT DIRECTORY: run the agent from sbx/.
80+skillsDir: ../skills
81+
82+# Persistent sessions, per project.
83+# When enabled, every conversation is saved as one JSON file under `dir`.
84+# `/sessions` lists them, `/resume` continues one; in an editor, "Reload Agent" replays the thread.
85+sessions:
86+ enabled: true
87+ dir: .mm/sessions
88+
89+# How many lines of a command's output are echoed to the terminal.
90+# 0 disables it.
91+previewLines: 20
92+
93+displayCommands: true
94+# Show what a thinking model reasons about before it answers (dim italic in the
95+# terminal, its own style in the window, a thought chunk in an editor).
96+# The reasoning is always READ — it is what keeps the watchdog alive while the
97+# model thinks — this only says whether to show it.
98+showThinking: true
99+
100+acp:
101+ name: lucy
102+ title: Lucy (coding agent)
103+
104+# The system prompt: what the agent is, and what it is allowed to do.
105+# This is the knob to play with — it is the shortest path to changing behaviour.
106+system: |
107+ Your name is Lucy.
108+ You are a coding agent working in a terminal.
109+ You have a "bash" tool to run shell commands.
110+ Use it to explore files, run tests, inspect the repository, etc.
111+ Chain several commands if needed, then answer clearly in English.
112+
113+ A request often mixes things you answer from yourself ("say hello") with
114+ things only a command can answer ("list the files"). Handle every part, in
115+ the order asked, and run a command for each part that needs one.
116+ Never state the contents of a file, the output of a command, or the state of
117+ the repository unless a command in THIS answer returned it. What you did not
118+ read, you do not know: run the command instead of recalling it.
119+
120+ SKILLS
121+ You have a second tool, `read_skill`. Its description lists the procedures
122+ available for this project — one per kind of task.
123+
124+ Any request to DO something to a Go project is a skill, not a shell command
125+ you invent. Match the request against that list, call `read_skill` FIRST,
126+ before any bash command, and then follow what it says step by step.
127+
128+ FILE EDITING
129+ You have three tools for files: `read_file`, `edit_file` and `write_file`.
130+ They are how a file gets read and changed here: each change is exact,
131+ checked before it is written, and comes back as a diff with line numbers.
132+ bash is for running things — building, testing, listing, searching.
133+
134+ - Read before you write: call `read_file` on the file (numbered=true when
135+ you need line numbers). You cannot target text you have not seen; never
136+ rely on what you think you remember about a file.
137+ - To change an existing file, call `edit_file` with one or more {old, new}
138+ pairs. `old` is copied from the file character for character — same
139+ spaces, same indentation, same line breaks — and appears exactly once:
140+ add the surrounding lines until it is unique. Several pairs are applied
141+ together, against the original file. An empty `new` deletes the text.
142+ - Call `write_file` only to create a file, or to rewrite one entirely and
143+ on purpose. On an existing file it replaces everything, including what
144+ you did not intend to touch.
145+ - Read the diff the tool returns: it says exactly what changed and on which
146+ line. If `edit_file` refuses — text not found, ambiguous, overlapping
147+ edits — read the file again and fix `old`. Do not fall back to
148+ `write_file` to force the change through.
149+ - After editing code, run the narrowest check with bash: the formatter, the
150+ compiler, or the test covering that file.
151+
152+ RULES
153+ - Keep everything the file already does, unless the user asked to remove it.
154+ - Touch only the files the request is about. Do not add tests, files or
155+ features that were not asked for.
156+ - Never run a git command unless the user says git, commit or push.
157+ - Never move, rename or delete a file unless the user asked for it.
158+ - Then answer in English, in a few lines.
159+ - If you don't know how to use a <cli>, run `<cli> --help` (or `<cli> help`)
160+ to understand the options, then run the command.
161+
162+ BACKGROUND JOBS
163+ Never let a command block the answer. Anything that serves, watches or runs
164+ long goes to the background, with BOTH streams redirected and its pid kept:
165+
166+ nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid
167+
168+ Redirecting only stdout still blocks until the process exits. Read the
169+ `bg-jobs` skill before you wait on, inspect or stop such a job — each has a
170+ rule you cannot guess. Stop every job you started before you finish, and say
171+ which ones you left running.
172+
173+# Generation settings (OpenAI API keys). Low temperature for a coding agent:
174+# we want precise and reproducible answers, not creativity.
175+sampling:
176+ temperature: 0.0
177+ parallel_tool_calls: false
178+ top_p: 0.9
179+ max_tokens: 4096
180+
181+# Silence allowed between two tokens once the answer has started.
182+watchdogTimeout: 30s
183+
184+# Silence allowed while the model reads the prompt, before the first token:
185+# on a laptop a 25k-token prompt can take minutes. llama-server reports its
186+# progress meanwhile, through llmman ("Reading the prompt 12.0k/25.3k tokens"), and each report
187+# restarts this clock, so it only has to cover one batch of the prompt.
188+firstTokenTimeout: 3m
189+
190+# Context compression.
191+# ON here: the agent learns the window from /api/ps, so `threshold` has a number to apply to.
192+context:
193+ enabled: true
194+
195+ # Compress when the history reaches this share of the window.
196+ threshold: 75
197+
198+ # Fallback on the message count, for when the window is unknown.
199+ # One command costs 2 messages (call + response), so 80 is roughly 30 commands of history.
200+ maxMessages: 80
201+
202+ # How many recent questions (with their commands and answers) are kept as-is instead of being summarised.
203+ # The model works on the last few turns, so summarising them would make it redo what it just did.
204+ keepLastTurns: 3
205+
206+ # max_tokens of the summary request. Reasoning is turned off for it on this provider
207+ # (a thinking model would otherwise spend the budget thinking and write nothing).
208+ summaryMaxTokens: 1200
209+
210+ showStats: true
added demo/agent.yaml +211 -0
new file mode 100644
@@ -0,0 +1,211 @@
1+# Agent settings — Jan: mini-me on hf.co/Menlo/Jan-nano-gguf:Q4_K_M, served by llmman (https://github.com/llmmanorg/llmman)
2+# through its OpenAI-compatible endpoint (/v1/chat/completions).
3+#
4+# llmman pull hf.co/Menlo/Jan-nano-gguf:Q4_K_M # optional: the first question pulls it otherwise
5+# llmman serve # 127.0.0.1:17434
6+#
7+# llmman loads the model on the first request (in its own llama-server) and
8+# unloads it after five idle minutes.
9+provider: llmman
10+
11+# The model id exactly as `llmman list` / GET /v1/models spells it.
12+model: hf.co/Menlo/Jan-nano-gguf:Q4_K_M
13+
14+# `llmman serve`'s default bind; the OpenAI routes sit under /v1.
15+baseUrl: http://127.0.0.1:17434/v1
16+
17+# From a Docker sandbox, the daemon runs on the host.
18+fallback: http://host.docker.internal:17434/v1
19+
20+# Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it
21+# listens beyond loopback); unset otherwise. The key never goes in this file.
22+# apiKeyEnv: LLMMAN_API_KEY
23+
24+# Yolo mode. `true` (default): the tools run without asking.
25+# `false`: every bash call, file write/edit, fetch_content save, lsp rename and plan change
26+# waits for your answer — [a] once, [s] for the session, [r] reject, [n] never — in the
27+# terminal, the window and the editor; MCP tools ask too.
28+# bashTool / editTools still decide which tools EXIST. Called through /ask (mmConfigs),
29+# an agent follows its asker's yolo, not this one. Override for one run: AGENT_YOLO=false.
30+yolo: true
31+
32+# The `bash` tool.
33+# `false` removes it: the model can still read and edit files (editTools) and load skills,
34+# but never runs a command. If you turn it off, reword the system prompt below — it says "You have a bash tool".
35+bashTool: true
36+
37+# The built-in file tools: read_file, write_file, edit_file.
38+editTools: true
39+
40+# The built-in plan tool for managing multi-step plans.
41+# Set to false to disable plan creation and tracking via the `plan` tool.
42+planTool: true
43+
44+# Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename).
45+# The file extension picks the server. A server missing from the PATH is skipped with a warning.
46+# No server listed = no `lsp` tool. Examples (uncomment what you have installed):
47+# lsp:
48+# servers:
49+# - name: gopls
50+# command: gopls
51+# extensions: [".go"]
52+# - name: typescript
53+# command: typescript-language-server
54+# args: ["--stdio"]
55+# extensions: [".ts", ".tsx", ".js", ".jsx"]
56+# - name: python
57+# command: pyright-langserver
58+# args: ["--stdio"]
59+# extensions: [".py"]
60+# - name: rust
61+# command: rust-analyzer
62+# extensions: [".rs"]
63+
64+# How many tokens the server actually serves.
65+# 0 = ask llmman: /api/ps tells it once the model is loaded, so the window is
66+# learned before the second question. Set it here if you want it from the start
67+# — and to the same value as LLMMAN_CONTEXT_LENGTH if you set that variable.
68+contextWindow: 0
69+
70+# Max number of characters a tool returns to the model.
71+# Context safeguard: beyond that, the output is truncated (beginning + end kept).
72+maxOutput: 16000
73+
74+# Max number of model <-> tools round trips for a single question.
75+# Raise it for tasks that need long chains of commands.
76+maxTurns: 40
77+
78+# Where the `read_skill` tool looks for its markdown procedures.
79+# The path is relative to the CURRENT DIRECTORY: run the agent from sbx/.
80+skillsDir: ../skills
81+
82+# Persistent sessions, per project.
83+# When enabled, every conversation is saved as one JSON file under `dir`.
84+# `/sessions` lists them, `/resume` continues one; in an editor, "Reload Agent" replays the thread.
85+sessions:
86+ enabled: true
87+ dir: .mm/sessions
88+
89+# How many lines of a command's output are echoed to the terminal.
90+# 0 disables it.
91+previewLines: 20
92+
93+displayCommands: true
94+# Show what a thinking model reasons about before it answers (dim italic in the
95+# terminal, its own style in the window, a thought chunk in an editor).
96+# The reasoning is always READ — it is what keeps the watchdog alive while the
97+# model thinks — this only says whether to show it.
98+showThinking: true
99+
100+
101+acp:
102+ name: jan
103+ title: Jan (coding agent)
104+
105+# The system prompt: what the agent is, and what it is allowed to do.
106+# This is the knob to play with — it is the shortest path to changing behaviour.
107+system: |
108+ Your name is Jan.
109+ You are a coding agent working in a terminal.
110+ You have a "bash" tool to run shell commands.
111+ Use it to explore files, run tests, inspect the repository, etc.
112+ Chain several commands if needed, then answer clearly in English.
113+
114+ A request often mixes things you answer from yourself ("say hello") with
115+ things only a command can answer ("list the files"). Handle every part, in
116+ the order asked, and run a command for each part that needs one.
117+ Never state the contents of a file, the output of a command, or the state of
118+ the repository unless a command in THIS answer returned it. What you did not
119+ read, you do not know: run the command instead of recalling it.
120+
121+ SKILLS
122+ You have a second tool, `read_skill`. Its description lists the procedures
123+ available for this project — one per kind of task.
124+
125+ Any request to DO something to a Go project is a skill, not a shell command
126+ you invent. Match the request against that list, call `read_skill` FIRST,
127+ before any bash command, and then follow what it says step by step.
128+
129+ FILE EDITING
130+ You have three tools for files: `read_file`, `edit_file` and `write_file`.
131+ They are how a file gets read and changed here: each change is exact,
132+ checked before it is written, and comes back as a diff with line numbers.
133+ bash is for running things — building, testing, listing, searching.
134+
135+ - Read before you write: call `read_file` on the file (numbered=true when
136+ you need line numbers). You cannot target text you have not seen; never
137+ rely on what you think you remember about a file.
138+ - To change an existing file, call `edit_file` with one or more {old, new}
139+ pairs. `old` is copied from the file character for character — same
140+ spaces, same indentation, same line breaks — and appears exactly once:
141+ add the surrounding lines until it is unique. Several pairs are applied
142+ together, against the original file. An empty `new` deletes the text.
143+ - Call `write_file` only to create a file, or to rewrite one entirely and
144+ on purpose. On an existing file it replaces everything, including what
145+ you did not intend to touch.
146+ - Read the diff the tool returns: it says exactly what changed and on which
147+ line. If `edit_file` refuses — text not found, ambiguous, overlapping
148+ edits — read the file again and fix `old`. Do not fall back to
149+ `write_file` to force the change through.
150+ - After editing code, run the narrowest check with bash: the formatter, the
151+ compiler, or the test covering that file.
152+
153+ RULES
154+ - Keep everything the file already does, unless the user asked to remove it.
155+ - Touch only the files the request is about. Do not add tests, files or
156+ features that were not asked for.
157+ - Never run a git command unless the user says git, commit or push.
158+ - Never move, rename or delete a file unless the user asked for it.
159+ - Then answer in English, in a few lines.
160+ - If you don't know how to use a <cli>, run `<cli> --help` (or `<cli> help`)
161+ to understand the options, then run the command.
162+
163+ BACKGROUND JOBS
164+ Never let a command block the answer. Anything that serves, watches or runs
165+ long goes to the background, with BOTH streams redirected and its pid kept:
166+
167+ nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid
168+
169+ Redirecting only stdout still blocks until the process exits. Read the
170+ `bg-jobs` skill before you wait on, inspect or stop such a job — each has a
171+ rule you cannot guess. Stop every job you started before you finish, and say
172+ which ones you left running.
173+
174+# Generation settings (OpenAI API keys). Low temperature for a coding agent:
175+# we want precise and reproducible answers, not creativity.
176+sampling:
177+ temperature: 0.0
178+ parallel_tool_calls: false
179+ top_p: 0.9
180+ max_tokens: 4096
181+
182+# Silence allowed between two tokens once the answer has started.
183+watchdogTimeout: 30s
184+
185+# Silence allowed while the model reads the prompt, before the first token:
186+# on a laptop a 25k-token prompt can take minutes. llama-server reports its
187+# progress meanwhile, through llmman ("Reading the prompt 12.0k/25.3k tokens"), and each report
188+# restarts this clock, so it only has to cover one batch of the prompt.
189+firstTokenTimeout: 3m
190+
191+# Context compression.
192+# ON here: the agent learns the window from /api/ps, so `threshold` has a number to apply to.
193+context:
194+ enabled: true
195+
196+ # Compress when the history reaches this share of the window.
197+ threshold: 75
198+
199+ # Fallback on the message count, for when the window is unknown.
200+ # One command costs 2 messages (call + response), so 80 is roughly 30 commands of history.
201+ maxMessages: 80
202+
203+ # How many recent questions (with their commands and answers) are kept as-is instead of being summarised.
204+ # The model works on the last few turns, so summarising them would make it redo what it just did.
205+ keepLastTurns: 3
206+
207+ # max_tokens of the summary request. Reasoning is turned off for it on this provider
208+ # (a thinking model would otherwise spend the budget thinking and write nothing).
209+ summaryMaxTokens: 1200
210+
211+ showStats: true
new file mode 100644
@@ -0,0 +1,211 @@
1+# Agent settings — Jan: mini-me on hf.co/Menlo/Jan-nano-gguf:Q4_K_M, served by llmman (https://github.com/llmmanorg/llmman)
2+# through its OpenAI-compatible endpoint (/v1/chat/completions).
3+#
4+# llmman pull hf.co/Menlo/Jan-nano-gguf:Q4_K_M # optional: the first question pulls it otherwise
5+# llmman serve # 127.0.0.1:17434
6+#
7+# llmman loads the model on the first request (in its own llama-server) and
8+# unloads it after five idle minutes.
9+provider: llmman
10+
11+# The model id exactly as `llmman list` / GET /v1/models spells it.
12+model: hf.co/Menlo/Jan-nano-gguf:Q4_K_M
13+
14+# `llmman serve`'s default bind; the OpenAI routes sit under /v1.
15+baseUrl: http://127.0.0.1:17434/v1
16+
17+# From a Docker sandbox, the daemon runs on the host.
18+fallback: http://host.docker.internal:17434/v1
19+
20+# Only when the daemon was started with LLMMAN_API_KEYS (mandatory when it
21+# listens beyond loopback); unset otherwise. The key never goes in this file.
22+# apiKeyEnv: LLMMAN_API_KEY
23+
24+# Yolo mode. `true` (default): the tools run without asking.
25+# `false`: every bash call, file write/edit, fetch_content save, lsp rename and plan change
26+# waits for your answer — [a] once, [s] for the session, [r] reject, [n] never — in the
27+# terminal, the window and the editor; MCP tools ask too.
28+# bashTool / editTools still decide which tools EXIST. Called through /ask (mmConfigs),
29+# an agent follows its asker's yolo, not this one. Override for one run: AGENT_YOLO=false.
30+yolo: true
31+
32+# The `bash` tool.
33+# `false` removes it: the model can still read and edit files (editTools) and load skills,
34+# but never runs a command. If you turn it off, reword the system prompt below — it says "You have a bash tool".
35+bashTool: true
36+
37+# The built-in file tools: read_file, write_file, edit_file.
38+editTools: true
39+
40+# The built-in plan tool for managing multi-step plans.
41+# Set to false to disable plan creation and tracking via the `plan` tool.
42+planTool: true
43+
44+# Language servers for the `lsp` tool (definition, references, hover, symbols, diagnostics, rename).
45+# The file extension picks the server. A server missing from the PATH is skipped with a warning.
46+# No server listed = no `lsp` tool. Examples (uncomment what you have installed):
47+# lsp:
48+# servers:
49+# - name: gopls
50+# command: gopls
51+# extensions: [".go"]
52+# - name: typescript
53+# command: typescript-language-server
54+# args: ["--stdio"]
55+# extensions: [".ts", ".tsx", ".js", ".jsx"]
56+# - name: python
57+# command: pyright-langserver
58+# args: ["--stdio"]
59+# extensions: [".py"]
60+# - name: rust
61+# command: rust-analyzer
62+# extensions: [".rs"]
63+
64+# How many tokens the server actually serves.
65+# 0 = ask llmman: /api/ps tells it once the model is loaded, so the window is
66+# learned before the second question. Set it here if you want it from the start
67+# — and to the same value as LLMMAN_CONTEXT_LENGTH if you set that variable.
68+contextWindow: 0
69+
70+# Max number of characters a tool returns to the model.
71+# Context safeguard: beyond that, the output is truncated (beginning + end kept).
72+maxOutput: 16000
73+
74+# Max number of model <-> tools round trips for a single question.
75+# Raise it for tasks that need long chains of commands.
76+maxTurns: 40
77+
78+# Where the `read_skill` tool looks for its markdown procedures.
79+# The path is relative to the CURRENT DIRECTORY: run the agent from sbx/.
80+skillsDir: ../skills
81+
82+# Persistent sessions, per project.
83+# When enabled, every conversation is saved as one JSON file under `dir`.
84+# `/sessions` lists them, `/resume` continues one; in an editor, "Reload Agent" replays the thread.
85+sessions:
86+ enabled: true
87+ dir: .mm/sessions
88+
89+# How many lines of a command's output are echoed to the terminal.
90+# 0 disables it.
91+previewLines: 20
92+
93+displayCommands: true
94+# Show what a thinking model reasons about before it answers (dim italic in the
95+# terminal, its own style in the window, a thought chunk in an editor).
96+# The reasoning is always READ — it is what keeps the watchdog alive while the
97+# model thinks — this only says whether to show it.
98+showThinking: true
99+
100+
101+acp:
102+ name: jan
103+ title: Jan (coding agent)
104+
105+# The system prompt: what the agent is, and what it is allowed to do.
106+# This is the knob to play with — it is the shortest path to changing behaviour.
107+system: |
108+ Your name is Jan.
109+ You are a coding agent working in a terminal.
110+ You have a "bash" tool to run shell commands.
111+ Use it to explore files, run tests, inspect the repository, etc.
112+ Chain several commands if needed, then answer clearly in English.
113+
114+ A request often mixes things you answer from yourself ("say hello") with
115+ things only a command can answer ("list the files"). Handle every part, in
116+ the order asked, and run a command for each part that needs one.
117+ Never state the contents of a file, the output of a command, or the state of
118+ the repository unless a command in THIS answer returned it. What you did not
119+ read, you do not know: run the command instead of recalling it.
120+
121+ SKILLS
122+ You have a second tool, `read_skill`. Its description lists the procedures
123+ available for this project — one per kind of task.
124+
125+ Any request to DO something to a Go project is a skill, not a shell command
126+ you invent. Match the request against that list, call `read_skill` FIRST,
127+ before any bash command, and then follow what it says step by step.
128+
129+ FILE EDITING
130+ You have three tools for files: `read_file`, `edit_file` and `write_file`.
131+ They are how a file gets read and changed here: each change is exact,
132+ checked before it is written, and comes back as a diff with line numbers.
133+ bash is for running things — building, testing, listing, searching.
134+
135+ - Read before you write: call `read_file` on the file (numbered=true when
136+ you need line numbers). You cannot target text you have not seen; never
137+ rely on what you think you remember about a file.
138+ - To change an existing file, call `edit_file` with one or more {old, new}
139+ pairs. `old` is copied from the file character for character — same
140+ spaces, same indentation, same line breaks — and appears exactly once:
141+ add the surrounding lines until it is unique. Several pairs are applied
142+ together, against the original file. An empty `new` deletes the text.
143+ - Call `write_file` only to create a file, or to rewrite one entirely and
144+ on purpose. On an existing file it replaces everything, including what
145+ you did not intend to touch.
146+ - Read the diff the tool returns: it says exactly what changed and on which
147+ line. If `edit_file` refuses — text not found, ambiguous, overlapping
148+ edits — read the file again and fix `old`. Do not fall back to
149+ `write_file` to force the change through.
150+ - After editing code, run the narrowest check with bash: the formatter, the
151+ compiler, or the test covering that file.
152+
153+ RULES
154+ - Keep everything the file already does, unless the user asked to remove it.
155+ - Touch only the files the request is about. Do not add tests, files or
156+ features that were not asked for.
157+ - Never run a git command unless the user says git, commit or push.
158+ - Never move, rename or delete a file unless the user asked for it.
159+ - Then answer in English, in a few lines.
160+ - If you don't know how to use a <cli>, run `<cli> --help` (or `<cli> help`)
161+ to understand the options, then run the command.
162+
163+ BACKGROUND JOBS
164+ Never let a command block the answer. Anything that serves, watches or runs
165+ long goes to the background, with BOTH streams redirected and its pid kept:
166+
167+ nohup <command> > /tmp/<job>.log 2>&1 & echo $! > /tmp/<job>.pid
168+
169+ Redirecting only stdout still blocks until the process exits. Read the
170+ `bg-jobs` skill before you wait on, inspect or stop such a job — each has a
171+ rule you cannot guess. Stop every job you started before you finish, and say
172+ which ones you left running.
173+
174+# Generation settings (OpenAI API keys). Low temperature for a coding agent:
175+# we want precise and reproducible answers, not creativity.
176+sampling:
177+ temperature: 0.0
178+ parallel_tool_calls: false
179+ top_p: 0.9
180+ max_tokens: 4096
181+
182+# Silence allowed between two tokens once the answer has started.
183+watchdogTimeout: 30s
184+
185+# Silence allowed while the model reads the prompt, before the first token:
186+# on a laptop a 25k-token prompt can take minutes. llama-server reports its
187+# progress meanwhile, through llmman ("Reading the prompt 12.0k/25.3k tokens"), and each report
188+# restarts this clock, so it only has to cover one batch of the prompt.
189+firstTokenTimeout: 3m
190+
191+# Context compression.
192+# ON here: the agent learns the window from /api/ps, so `threshold` has a number to apply to.
193+context:
194+ enabled: true
195+
196+ # Compress when the history reaches this share of the window.
197+ threshold: 75
198+
199+ # Fallback on the message count, for when the window is unknown.
200+ # One command costs 2 messages (call + response), so 80 is roughly 30 commands of history.
201+ maxMessages: 80
202+
203+ # How many recent questions (with their commands and answers) are kept as-is instead of being summarised.
204+ # The model works on the last few turns, so summarising them would make it redo what it just did.
205+ keepLastTurns: 3
206+
207+ # max_tokens of the summary request. Reasoning is turned off for it on this provider
208+ # (a thinking model would otherwise spend the budget thinking and write nothing).
209+ summaryMaxTokens: 1200
210+
211+ showStats: true
added git.sh +136 -0
new file mode 100755
@@ -0,0 +1,136 @@
1+#!/bin/bash
2+message=""
3+case $1 in
4+
5+ # 🎨: art
6+ art)
7+ message="Improve structure / format of the code"
8+ emoji="🎨"
9+ ;;
10+
11+ # 🐛: bug
12+ bug|fix)
13+ message="Fix a bug"
14+ emoji="🐛"
15+ ;;
16+
17+ # 🤓: geek
18+ human|human-fixed)
19+ message="Human Fixed"
20+ emoji="🤓"
21+ ;;
22+
23+ # 🤖: robot
24+ ai|ai-generated)
25+ message="AI generated"
26+ emoji="🤖"
27+ ;;
28+
29+ # ✨: sparkles
30+ sparkles|feature)
31+ message="Introduce new feature(s)"
32+ emoji="✨"
33+ ;;
34+
35+ # 🧩: jigsaw
36+ jigsaw|example|examples|demo|demos)
37+ message="Introduce new example(s)"
38+ emoji="🧩"
39+ ;;
40+
41+
42+ # 📝: memo
43+ memo|doc|documentation)
44+ message="Add or update documentation"
45+ emoji="📝"
46+ ;;
47+
48+ # 🌸: cherry_blossom
49+ gardening|garden|clean|cleaning)
50+ message="Gardening"
51+ emoji="🌸"
52+ ;;
53+
54+ # 🚀: rocket
55+ rocket|deploy)
56+ message="Deploy stuff"
57+ emoji="🚀"
58+ ;;
59+
60+ # 🎉: tada
61+ tada|first)
62+ message="Begin a project"
63+ emoji="🎉"
64+ ;;
65+
66+ # 🚧: construction
67+ construction|wip)
68+ message="Work in progress"
69+ emoji="🚧"
70+ ;;
71+
72+ # 📦️: package
73+ package|build)
74+ message="Add or update compiled files or packages"
75+ emoji="📦️"
76+ ;;
77+
78+ # 📦️: package
79+ release)
80+ message="Create a release"
81+ emoji="📦️"
82+ ;;
83+
84+ # 👽️: alien
85+ alien|api)
86+ message="Update code due to external API changes"
87+ emoji="👽️"
88+ ;;
89+
90+ # 🐳: whale
91+ docker|container)
92+ message="Docker"
93+ emoji="🐳"
94+ ;;
95+
96+ # 🍊: tangerine
97+ gitpod|gitpodify)
98+ message="Gitpodify"
99+ emoji="🍊"
100+ ;;
101+
102+ # 🧪: test tube
103+ alembic|experiments|experiment|xp)
104+ message="Perform experiments"
105+ emoji="🧪"
106+ ;;
107+
108+ # ✅: check mark
109+ test|tests|testing)
110+ message="Add or update tests"
111+ emoji="✅"
112+ ;;
113+
114+ # 💾: floppy-disk
115+ save)
116+ message="Saved"
117+ emoji="💾"
118+ ;;
119+
120+ *)
121+ message="Updated"
122+ emoji="🛟"
123+ ;;
124+
125+esac
126+
127+find . -name '.DS_Store' -type f -delete
128+
129+if [ -z "$2" ]
130+then
131+ # empty
132+ git add .; git commit -m "$emoji $message."; git push
133+else
134+ # not empty
135+ git add .; git commit -m "$emoji $message: $2"; git push
136+fi
new file mode 100755
@@ -0,0 +1,136 @@
1+#!/bin/bash
2+message=""
3+case $1 in
4+
5+ # 🎨: art
6+ art)
7+ message="Improve structure / format of the code"
8+ emoji="🎨"
9+ ;;
10+
11+ # 🐛: bug
12+ bug|fix)
13+ message="Fix a bug"
14+ emoji="🐛"
15+ ;;
16+
17+ # 🤓: geek
18+ human|human-fixed)
19+ message="Human Fixed"
20+ emoji="🤓"
21+ ;;
22+
23+ # 🤖: robot
24+ ai|ai-generated)
25+ message="AI generated"
26+ emoji="🤖"
27+ ;;
28+
29+ # ✨: sparkles
30+ sparkles|feature)
31+ message="Introduce new feature(s)"
32+ emoji="✨"
33+ ;;
34+
35+ # 🧩: jigsaw
36+ jigsaw|example|examples|demo|demos)
37+ message="Introduce new example(s)"
38+ emoji="🧩"
39+ ;;
40+
41+
42+ # 📝: memo
43+ memo|doc|documentation)
44+ message="Add or update documentation"
45+ emoji="📝"
46+ ;;
47+
48+ # 🌸: cherry_blossom
49+ gardening|garden|clean|cleaning)
50+ message="Gardening"
51+ emoji="🌸"
52+ ;;
53+
54+ # 🚀: rocket
55+ rocket|deploy)
56+ message="Deploy stuff"
57+ emoji="🚀"
58+ ;;
59+
60+ # 🎉: tada
61+ tada|first)
62+ message="Begin a project"
63+ emoji="🎉"
64+ ;;
65+
66+ # 🚧: construction
67+ construction|wip)
68+ message="Work in progress"
69+ emoji="🚧"
70+ ;;
71+
72+ # 📦️: package
73+ package|build)
74+ message="Add or update compiled files or packages"
75+ emoji="📦️"
76+ ;;
77+
78+ # 📦️: package
79+ release)
80+ message="Create a release"
81+ emoji="📦️"
82+ ;;
83+
84+ # 👽️: alien
85+ alien|api)
86+ message="Update code due to external API changes"
87+ emoji="👽️"
88+ ;;
89+
90+ # 🐳: whale
91+ docker|container)
92+ message="Docker"
93+ emoji="🐳"
94+ ;;
95+
96+ # 🍊: tangerine
97+ gitpod|gitpodify)
98+ message="Gitpodify"
99+ emoji="🍊"
100+ ;;
101+
102+ # 🧪: test tube
103+ alembic|experiments|experiment|xp)
104+ message="Perform experiments"
105+ emoji="🧪"
106+ ;;
107+
108+ # ✅: check mark
109+ test|tests|testing)
110+ message="Add or update tests"
111+ emoji="✅"
112+ ;;
113+
114+ # 💾: floppy-disk
115+ save)
116+ message="Saved"
117+ emoji="💾"
118+ ;;
119+
120+ *)
121+ message="Updated"
122+ emoji="🛟"
123+ ;;
124+
125+esac
126+
127+find . -name '.DS_Store' -type f -delete
128+
129+if [ -z "$2" ]
130+then
131+ # empty
132+ git add .; git commit -m "$emoji $message."; git push
133+else
134+ # not empty
135+ git add .; git commit -m "$emoji $message: $2"; git push
136+fi
added mini-me/mini-me.dockerfile +21 -0
new file mode 100644
@@ -0,0 +1,21 @@
1+# syntax=docker/dockerfile:1
2+#
3+# Base: Docker's shell template = Ubuntu, non-root `agent` user (UID 1000),
4+# bash, git, curl, CA certificates. No agent pre-installed.
5+FROM docker/sandbox-templates:shell
6+
7+USER root
8+
9+ARG TARGETARCH
10+ARG MM_VERSION
11+
12+RUN <<EOF
13+set -eu
14+curl -fsSL "https://rickub.com/bots-garden/mini-me/releases/download/${MM_VERSION}/mm-${MM_VERSION#v}-linux-${TARGETARCH}" -o /usr/local/bin/mm
15+chmod 0755 /usr/local/bin/mm
16+EOF
17+
18+# Back to the sandbox user, then declare the launch command.
19+USER agent
20+ENTRYPOINT ["mm"]
21+CMD ["-tui"]
new file mode 100644
@@ -0,0 +1,21 @@
1+# syntax=docker/dockerfile:1
2+#
3+# Base: Docker's shell template = Ubuntu, non-root `agent` user (UID 1000),
4+# bash, git, curl, CA certificates. No agent pre-installed.
5+FROM docker/sandbox-templates:shell
6+
7+USER root
8+
9+ARG TARGETARCH
10+ARG MM_VERSION
11+
12+RUN <<EOF
13+set -eu
14+curl -fsSL "https://rickub.com/bots-garden/mini-me/releases/download/${MM_VERSION}/mm-${MM_VERSION#v}-linux-${TARGETARCH}" -o /usr/local/bin/mm
15+chmod 0755 /usr/local/bin/mm
16+EOF
17+
18+# Back to the sandbox user, then declare the launch command.
19+USER agent
20+ENTRYPOINT ["mm"]
21+CMD ["-tui"]
added mini-me/mini-me.yaml +31 -0
new file mode 100644
@@ -0,0 +1,31 @@
1+# syntax=docker/sandbox-kit:3
2+schemaVersion: "3"
3+kind: workload
4+displayName: Mini Me
5+description: Mini Me (mm), a minimalist coding agent for local LLMs
6+sourceUrl: https://rickub.com/bots-garden/mini-me
7+
8+provides: ["mini-me@0.3.0"]
9+
10+dockerfile: ./mini-me.dockerfile
11+
12+args:
13+ mm_version:
14+ # A release tag of https://rickub.com/bots-garden/mini-me/releases
15+ default: "v0.3.0"
16+ pattern: '^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'
17+ buildArg: MM_VERSION
18+
19+capabilities:
20+ # The workload is prepared for sbx to launch it (agent user, bash, ...).
21+ - type: com.docker.sandbox/sbx@1
22+
23+ # Egress is deny-by-default. mm talks to a model server running on the host.
24+ # Check the port/host for your setup, then `sbx policy log` if it is blocked.
25+ - type: com.docker.sandbox/network-policy@1
26+ config:
27+ runtime:
28+ allow:
29+ - host.docker.internal:12434 # Docker Model Runner
30+ - host.docker.internal:11434 # Ollama
31+ - host.docker.internal:17434 # Llmman
new file mode 100644
@@ -0,0 +1,31 @@
1+# syntax=docker/sandbox-kit:3
2+schemaVersion: "3"
3+kind: workload
4+displayName: Mini Me
5+description: Mini Me (mm), a minimalist coding agent for local LLMs
6+sourceUrl: https://rickub.com/bots-garden/mini-me
7+
8+provides: ["mini-me@0.3.0"]
9+
10+dockerfile: ./mini-me.dockerfile
11+
12+args:
13+ mm_version:
14+ # A release tag of https://rickub.com/bots-garden/mini-me/releases
15+ default: "v0.3.0"
16+ pattern: '^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$'
17+ buildArg: MM_VERSION
18+
19+capabilities:
20+ # The workload is prepared for sbx to launch it (agent user, bash, ...).
21+ - type: com.docker.sandbox/sbx@1
22+
23+ # Egress is deny-by-default. mm talks to a model server running on the host.
24+ # Check the port/host for your setup, then `sbx policy log` if it is blocked.
25+ - type: com.docker.sandbox/network-policy@1
26+ config:
27+ runtime:
28+ allow:
29+ - host.docker.internal:12434 # Docker Model Runner
30+ - host.docker.internal:11434 # Ollama
31+ - host.docker.internal:17434 # Llmman
added release.env +5 -0
new file mode 100644
@@ -0,0 +1,5 @@
1+# ./01-release.tag.sh commit, tag, push
2+TAG="v0.0.0"
3+ABOUT="Mini Me"
4+OWNER="bots-garden"
5+REPO="mini-me-kit"
new file mode 100644
@@ -0,0 +1,5 @@
1+# ./01-release.tag.sh commit, tag, push
2+TAG="v0.0.0"
3+ABOUT="Mini Me"
4+OWNER="bots-garden"
5+REPO="mini-me-kit"