bots-garden/mini-mepublic Fork
⑂ v0.1.6
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.

Download ZIP
🛟 Updated. 37a5a39 · on v0.1.6 · k33g · Sep 21, 2026
slash-commands.md · 135 lines · 11.0 KBmarkdown
Blame HistoryOpen raw

Reference: slash commands and keyboard shortcuts

Neutral description of the commands recognised at the terminal prompt of mm. They are matched on the whole trimmed line; anything else is sent to the model.

Commands

Command At the prompt During a generation
/quit Exits the program. Cancels the generation, prints Goodbye., exits.
/abort Prints ⚠️ No generation in progress. Cancels the generation, prints 🛑 Aborting...; the commands already run stay in the history.
/compact Compresses the history now, regardless of the threshold; prints the 🗜️ report, or 🗜️ nothing to compact when no turn is older than context.keepLastTurns. Sent to the model as a new message (see below).
/new Clears the history back to the system prompt, resets the loop detector and forgets the server's last token count; prints 🆕 new session: N message(s) forgotten (N counts every message except the system prompt). Treated like any other text: cancels the generation, keeps its partial history, then runs as /new on that history.
/sessions Lists the project's stored sessions, newest first: id, last update, question count, first question, then · ⚠️ N error(s) when the session recorded errors; * marks the current one. With sessions.enabled: false: ⚠️ sessions are off (set sessions.enabled: true in the YAML). Sent to the model as a new message.
/resume [id] Continues a stored session: the most recently updated one other than the current, skipping empty ones, or the named id. Prints ↩️ resumed <id> — N message(s), started with "<first question>" (plus · ⚠️ N error(s) when the session recorded errors); resets the loop detector and the server's token count; later turns are saved to that session. Refused with a ⚠️ reason when sessions are off, when there is no earlier session, when the id is unknown or is the current session. Sent to the model as a new message.
/help Prints the commands of this front end, one per line with their description, aligned. Sent to the model as a new message.
/copy [n|all] Copies the last answer (n: the n-th from the end) to the clipboard through pbcopy/wl-copy/xclip/xsel or, failing that, OSC 52 when stdout is a terminal, and prints 📋 copied N chars (<road>) or ⚠️ …. /copy all is window-mode only: here it says so. Sent to the model as a new message.

With sessions.enabled, /new leaves the current session's file as it is; the next question opens a new file. An empty line at the prompt is ignored.

@path in a question

Input Effect
@<path> at the start or after a space, bracket or quote If the path exists (relative to the start directory, absolute, or ~/…), a dim 📎 <absolute path> line is printed and [attached file: <absolute path>] (or [attached directory: …]) is appended to the message the model receives. Trailing punctuation is ignored; each path is attached once.
A @<path> that names nothing on disk, or @ glued to a word Left as typed.

Details and examples: Point the model at a file with @path.

Any other text during a generation

Input Behaviour
A non-command line Prints 🔄 New command received. Cancelling current task..., cancels the current generation, keeps its partial history, then submits the new line as the next question.

Keyboard shortcuts

Key At the prompt During a generation
Ctrl+C Prints Goodbye. and exits. Prints 🛑 Interrupted (Ctrl+C). and cancels the generation; the prompt comes back.
Ctrl+D (end of input) Exits. —

Window mode keys

In mm -tui the same commands exist; /abort when idle prints ⚠️ No generation in progress. as a notice, and the picker opened by / lists them — see The three pickers.

/quit and /abort take effect immediately, even while a turn is running. Every other command and every question waits for the turn to end, because it needs the history the turn is still writing. See Leaving a turn that will not stop.

The keys:

Key Action
Enter Sends the box (nothing on an empty box). With the picker open on an incomplete name, completes it instead.
Ctrl-J, Alt-Enter Inserts a newline in the box.
Esc Cancels the running turn (same as /abort); closes the picker; rejects a pending permission.
Ctrl-C Cancels the running turn; quits when idle — and quits too when the turn has already been asked to stop and has not.
Tab Moves the focus between the box and the conversation; completes the picker's choice when it is open (/, @ or $).
↑ ↓ In the box: move between its rows — a long line wraps at spaces into several rows — and scroll the conversation from its first/last row. On the conversation: scroll one line. In the picker: move the choice.
PgUp PgDn Scroll one page.
Home End In the box: start/end of the line. On the conversation: top / bottom (bottom resumes following).
Ctrl-L Clears the displayed conversation; the history is kept.
F1 Same as /help.
F2 Toggles mouse capture. Off (default): the terminal's own click-and-drag selection works; the status bar says F2 mouse: off. On: the wheel scrolls, Shift+drag selects, the status bar says mouse: on (Shift+drag selects).
Ctrl-Y Same as /copy: the last answer to the clipboard.
a s r Answer a pending permission: allow once, allow this tool for the session, reject.
Mouse wheel Scrolls the conversation — only while the mouse is captured (F2).
Bracketed paste Inserted as one block; its line breaks become newlines, never a send. Longer than 3 lines or 200 characters: collapsed into one [Pasted #n · L lines · C chars] token that edits as a single character; Enter sends the full text, the conversation keeps the token. @path inside a paste is not looked up.

Leaving a turn that will not stop

A turn normally ends when it is cancelled. A turn that ignores the cancellation — an engine that stopped answering, a tool blocked on something that never returns — used to trap the window: /quit and /abort waited for the turn to end, so they never ran, and Ctrl-C read "there is a turn to cancel" as "so do not quit". The only way out was to kill mm from another terminal.

The way out, in order:

You do The window does
Esc or /abort Cancels the turn, and says 🛑 Aborting….
Esc or /abort again The turn is still there: ⚠️ The turn is not answering the cancellation — press Ctrl-C (or /quit) to leave mm.
Ctrl-C Cancels, as above.
Ctrl-C again Leaves mm, turn or no turn.
/quit Leaves mm at once, at any moment.

Leaving this way does not wait for the stuck job: the session file holds everything saved up to the last completed turn.

The three pickers

A popup opens over the conversation as you type one of three triggers, and narrows as you type more. Tab completes the highlighted row, ↑/↓ move, Esc dismisses it until the text changes.

Trigger Offers Where it works What Tab writes
/ the window's commands only as the whole first word of the box — a command is the message the command, replacing the box, with a space when it takes an argument
@ files and directories under the working directory anywhere in a sentence the path with its @ kept. A directory gets a trailing / and no space, so Tab again walks down the tree; a file gets a space, so the sentence continues
$ the skills of the catalogue anywhere in a sentence $name — the $ kept — plus a space, with the cursor after it, ready for the skill's parameters

Three rules keep the popup out of the way:

  • A trigger glued to the end of a word is not a trigger: bob@example.com opens nothing, and neither does 5$.
  • @ hides dotfiles until you type the . yourself.
  • $ offers nothing when no skill matches, so echo $HOME and $PATH are left alone.

Enter on a @ or $ token completes it rather than sending: the message is not finished. Enter on a command whose name is already complete sends it.

What $name does when sent

$greetings Bob Morane appends one line to what the model reads, the same way @path appends an attachment line:

use $greetings Bob Morane
[skill: greetings — load it with read_skill and carry out its steps now; parameters: Bob Morane]

The parameters are the rest of the line. The model still makes the read_skill call itself, so the loop detector, the permission gate and the 📖 N skill(s) recap all see it — mm does not load the skill behind the model's back.

The notation works in the line mode and over ACP too, typed by hand: a $skill means the same thing wherever it is written, as @path does. A $name that matches no skill is left alone, and a $ inside a collapsed paste is not looked up.

Messages printed at the end of a turn

Message Meaning
🛑 Generation aborted. The turn was cancelled (/abort, Ctrl+C). The question and any completed tool turns stay in the history.
[error: …] The provider explained a failure in one line; a question that got no answer is removed from the history.
⚙ N command(s) Number of bash commands that actually ran in the turn.
· 📝 N file op(s) Appended when file tools ran.
· 📖 N skill(s) Appended when skills were loaded.
Numbered green list The commands and file operations of the turn, one per line, when displayCommands: true.

ACP mode

Two commands exist in ACP mode: /new and /compact. They are advertised to the editor through an available_commands_update notification and intercepted by session/prompt when the prompt text, trimmed, is exactly the command. Each answers with one agent_message_chunk carrying the line the terminal would print, then stopReason: end_turn; the model is not consulted.

Command Over ACP
/new Same as in the terminal: history back to the system prompt, token count forgotten; the session id, cwd and allow-always grants are kept.
/compact Same as in the terminal, always forced: 🗜️ compressed …, 🗜️ nothing to compact: … or [compact: failed, history kept: …]. Waits for a running turn to finish first.

/quit and /abort do not exist in ACP mode: the editor owns the process and ends it by closing stdin, and cancels a turn with its own stop key through session/cancel. Each skill is offered there as a command of its own — ACP has no picker for skills, so /greetings Bob in the editor's menu is the equivalent of $greetings Bob in the window, and it is rewritten into exactly that. See the ACP reference.

  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
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# Reference: slash commands and keyboard shortcuts

> Neutral description of the commands recognised at the terminal prompt of `mm`. They are matched on the whole trimmed line; anything else is sent to the model.

## Commands

| Command | At the prompt | During a generation |
|---------|---------------|---------------------|
| `/quit` | Exits the program. | Cancels the generation, prints `Goodbye.`, exits. |
| `/abort` | Prints `⚠️ No generation in progress.` | Cancels the generation, prints `🛑 Aborting...`; the commands already run stay in the history. |
| `/compact` | Compresses the history now, regardless of the threshold; prints the `🗜️` report, or `🗜️ nothing to compact` when no turn is older than `context.keepLastTurns`. | Sent to the model as a new message (see below). |
| `/new` | Clears the history back to the system prompt, resets the loop detector and forgets the server's last token count; prints `🆕 new session: N message(s) forgotten` (N counts every message except the system prompt). | Treated like any other text: cancels the generation, keeps its partial history, then runs as `/new` on that history. |
| `/sessions` | Lists the project's stored sessions, newest first: id, last update, question count, first question, then ` · ⚠️ N error(s)` when the session recorded errors; `*` marks the current one. With `sessions.enabled: false`: `⚠️ sessions are off (set sessions.enabled: true in the YAML)`. | Sent to the model as a new message. |
| `/resume [id]` | Continues a stored session: the most recently updated one other than the current, skipping empty ones, or the named id. Prints `↩️ resumed <id> — N message(s), started with "<first question>"` (plus ` · ⚠️ N error(s)` when the session recorded errors); resets the loop detector and the server's token count; later turns are saved to that session. Refused with a `⚠️` reason when sessions are off, when there is no earlier session, when the id is unknown or is the current session. | Sent to the model as a new message. |
| `/help` | Prints the commands of this front end, one per line with their description, aligned. | Sent to the model as a new message. |
| `/copy [n\|all]` | Copies the last answer (`n`: the n-th from the end) to the clipboard through `pbcopy`/`wl-copy`/`xclip`/`xsel` or, failing that, OSC 52 when stdout is a terminal, and prints `📋 copied N chars (<road>)` or `⚠️ …`. `/copy all` is window-mode only: here it says so. | Sent to the model as a new message. |

With `sessions.enabled`, `/new` leaves the current session's file as it is; the next question opens a new file. An empty line at the prompt is ignored.

## `@path` in a question

| Input | Effect |
|-------|--------|
| `@<path>` at the start or after a space, bracket or quote | If the path exists (relative to the start directory, absolute, or `~/…`), a dim `📎 <absolute path>` line is printed and `[attached file: <absolute path>]` (or `[attached directory: …]`) is appended to the message the model receives. Trailing punctuation is ignored; each path is attached once. |
| A `@<path>` that names nothing on disk, or `@` glued to a word | Left as typed. |

Details and examples: [Point the model at a file with `@path`](../how-to/attach-a-file.md).

## Any other text during a generation

| Input | Behaviour |
|-------|-----------|
| A non-command line | Prints `🔄 New command received. Cancelling current task...`, cancels the current generation, keeps its partial history, then submits the new line as the next question. |

## Keyboard shortcuts

| Key | At the prompt | During a generation |
|-----|---------------|---------------------|
| `Ctrl+C` | Prints `Goodbye.` and exits. | Prints `🛑 Interrupted (Ctrl+C).` and cancels the generation; the prompt comes back. |
| `Ctrl+D` (end of input) | Exits. | — |

## Window mode keys

In `mm -tui` the same commands exist; `/abort` when idle prints `⚠️ No generation in progress.` as a notice, and the picker opened by `/` lists them — see [The three pickers](#the-three-pickers).

`/quit` and `/abort` take effect **immediately**, even while a turn is running. Every other command and every question waits for the turn to end, because it needs the history the turn is still writing. See [Leaving a turn that will not stop](#leaving-a-turn-that-will-not-stop).

The keys:

| Key | Action |
|-----|--------|
| `Enter` | Sends the box (nothing on an empty box). With the picker open on an incomplete name, completes it instead. |
| `Ctrl-J`, `Alt-Enter` | Inserts a newline in the box. |
| `Esc` | Cancels the running turn (same as `/abort`); closes the picker; rejects a pending permission. |
| `Ctrl-C` | Cancels the running turn; quits when idle — and quits too when the turn has already been asked to stop and has not. |
| `Tab` | Moves the focus between the box and the conversation; completes the picker's choice when it is open (`/`, `@` or `$`). |
| `↑` `↓` | In the box: move between its rows — a long line wraps at spaces into several rows — and scroll the conversation from its first/last row. On the conversation: scroll one line. In the picker: move the choice. |
| `PgUp` `PgDn` | Scroll one page. |
| `Home` `End` | In the box: start/end of the line. On the conversation: top / bottom (bottom resumes following). |
| `Ctrl-L` | Clears the displayed conversation; the history is kept. |
| `F1` | Same as `/help`. |
| `F2` | Toggles mouse capture. Off (default): the terminal's own click-and-drag selection works; the status bar says `F2 mouse: off`. On: the wheel scrolls, `Shift`+drag selects, the status bar says `mouse: on (Shift+drag selects)`. |
| `Ctrl-Y` | Same as `/copy`: the last answer to the clipboard. |
| `a` `s` `r` | Answer a pending permission: allow once, allow this tool for the session, reject. |
| Mouse wheel | Scrolls the conversation — only while the mouse is captured (F2). |
| Bracketed paste | Inserted as one block; its line breaks become newlines, never a send. Longer than 3 lines or 200 characters: collapsed into one `[Pasted #n · L lines · C chars]` token that edits as a single character; Enter sends the full text, the conversation keeps the token. `@path` inside a paste is not looked up. |

## Leaving a turn that will not stop

A turn normally ends when it is cancelled. A turn that ignores the cancellation — an engine that stopped answering, a tool blocked on something that never returns — used to trap the window: `/quit` and `/abort` waited for the turn to end, so they never ran, and `Ctrl-C` read "there is a turn to cancel" as "so do not quit". The only way out was to kill `mm` from another terminal.

The way out, in order:

| You do | The window does |
|--------|-----------------|
| `Esc` or `/abort` | Cancels the turn, and says `🛑 Aborting…`. |
| `Esc` or `/abort` again | The turn is still there: `⚠️ The turn is not answering the cancellation — press Ctrl-C (or /quit) to leave mm.` |
| `Ctrl-C` | Cancels, as above. |
| `Ctrl-C` again | Leaves `mm`, turn or no turn. |
| `/quit` | Leaves `mm` at once, at any moment. |

Leaving this way does not wait for the stuck job: the session file holds everything saved up to the last completed turn.

## The three pickers

A popup opens over the conversation as you type one of three triggers, and narrows as you type more. **Tab** completes the highlighted row, **↑/↓** move, **Esc** dismisses it until the text changes.

| Trigger | Offers | Where it works | What Tab writes |
|---|---|---|---|
| `/` | the window's commands | only as the whole first word of the box — a command *is* the message | the command, replacing the box, with a space when it takes an argument |
| `@` | files and directories under the working directory | anywhere in a sentence | the path with its `@` kept. A **directory** gets a trailing `/` and no space, so Tab again walks down the tree; a **file** gets a space, so the sentence continues |
| `$` | the skills of the catalogue | anywhere in a sentence | `$name` — the `$` **kept** — plus a space, with the cursor after it, ready for the skill's parameters |

Three rules keep the popup out of the way:

- A trigger glued to the end of a word is not a trigger: `bob@example.com` opens nothing, and neither does `5$`.
- `@` hides dotfiles until you type the `.` yourself.
- `$` offers nothing when no skill matches, so `echo $HOME` and `$PATH` are left alone.

`Enter` on a `@` or `$` token completes it rather than sending: the message is not finished. `Enter` on a command whose name is already complete sends it.

### What `$name` does when sent

`$greetings Bob Morane` appends one line to what the model reads, the same way `@path` appends an attachment line:

```
use $greetings Bob Morane
[skill: greetings — load it with read_skill and carry out its steps now; parameters: Bob Morane]
```

The parameters are the rest of the line. The model still makes the `read_skill` call itself, so the loop detector, the permission gate and the `📖 N skill(s)` recap all see it — `mm` does not load the skill behind the model's back.

The notation works in the line mode and over ACP too, typed by hand: a `$skill` means the same thing wherever it is written, as `@path` does. A `$name` that matches no skill is left alone, and a `$` inside a collapsed paste is not looked up.

## Messages printed at the end of a turn

| Message | Meaning |
|---------|---------|
| `🛑 Generation aborted.` | The turn was cancelled (`/abort`, `Ctrl+C`). The question and any completed tool turns stay in the history. |
| `[error: …]` | The provider explained a failure in one line; a question that got no answer is removed from the history. |
| `⚙ N command(s)` | Number of `bash` commands that actually ran in the turn. |
| `· 📝 N file op(s)` | Appended when file tools ran. |
| `· 📖 N skill(s)` | Appended when skills were loaded. |
| Numbered green list | The commands and file operations of the turn, one per line, when `displayCommands: true`. |

## ACP mode

Two commands exist in ACP mode: `/new` and `/compact`. They are advertised to the editor through an `available_commands_update` notification and intercepted by `session/prompt` when the prompt text, trimmed, is exactly the command. Each answers with one `agent_message_chunk` carrying the line the terminal would print, then `stopReason: end_turn`; the model is not consulted.

| Command | Over ACP |
|---------|----------|
| `/new` | Same as in the terminal: history back to the system prompt, token count forgotten; the session id, `cwd` and allow-always grants are kept. |
| `/compact` | Same as in the terminal, always forced: `🗜️ compressed …`, `🗜️ nothing to compact: …` or `[compact: failed, history kept: …]`. Waits for a running turn to finish first. |

`/quit` and `/abort` do not exist in ACP mode: the editor owns the process and ends it by closing stdin, and cancels a turn with its own stop key through `session/cancel`. Each **skill** is offered there as a command of its own — ACP has no picker for skills, so `/greetings Bob` in the editor's menu is the equivalent of `$greetings Bob` in the window, and it is rewritten into exactly that. See the [ACP reference](acp.md#skills-as-commands).