modified
.tickets/issues/0032-add-prompt-flag.yaml +2 -2 | @@ -1,12 +1,12 @@ | ||
| 1 | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | 2 | id: 32 |
| 3 | 3 | title: Add --prompt flag |
| 4 | -state: open | |
| 4 | +state: closed | |
| 5 | 5 | author: |
| 6 | 6 | name: k33g |
| 7 | 7 | email: ph.charriere@gmail.com |
| 8 | 8 | createdAt: 2026-09-21T04:47:19.089Z |
| 9 | -updatedAt: 2026-09-22T21:02:05.404Z | |
| 9 | +updatedAt: 2026-09-22T21:20:18.060Z | |
| 10 | 10 | labels: [] |
| 11 | 11 | milestone: v0.1.1 |
| 12 | 12 | epic: CLI |
| @@ -1,12 +1,12 @@ | |||
| 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. | 1 | # Managed by IssueSpec. Hand edits are welcome; keep the schema valid. |
| 2 | id: 32 | 2 | id: 32 |
| 3 | title: Add --prompt flag | 3 | title: Add --prompt flag |
| 4 | -state: open | 4 | +state: closed |
| 5 | author: | 5 | author: |
| 6 | name: k33g | 6 | name: k33g |
| 7 | email: ph.charriere@gmail.com | 7 | email: ph.charriere@gmail.com |
| 8 | createdAt: 2026-09-21T04:47:19.089Z | 8 | createdAt: 2026-09-21T04:47:19.089Z |
| 9 | -updatedAt: 2026-09-22T21:02:05.404Z | 9 | +updatedAt: 2026-09-22T21:20:18.060Z |
| 10 | labels: [] | 10 | labels: [] |
| 11 | milestone: v0.1.1 | 11 | milestone: v0.1.1 |
| 12 | epic: CLI | 12 | epic: CLI |
modified
docs/en/README.md +1 -0 | @@ -21,6 +21,7 @@ This documentation is organised along the four [Diátaxis](https://diataxis.fr) | ||
| 21 | 21 | - [Keep sessions and resume them](how-to/keep-sessions.md) |
| 22 | 22 | - [Use the window mode (`mm -tui`)](how-to/use-the-window-mode.md) |
| 23 | 23 | - [Navigate and refactor code with a language server (`lsp`)](how-to/navigate-code-with-lsp.md) |
| 24 | +- [Run a single prompt and exit (`-p`/`--prompt`)](how-to/run-a-single-prompt.md) | |
| 24 | 25 | |
| 25 | 26 | ## Reference — look it up |
| 26 | 27 | |
| @@ -21,6 +21,7 @@ This documentation is organised along the four [Diátaxis](https://diataxis.fr) | |||
| 21 | - [Keep sessions and resume them](how-to/keep-sessions.md) | 21 | - [Keep sessions and resume them](how-to/keep-sessions.md) |
| 22 | - [Use the window mode (`mm -tui`)](how-to/use-the-window-mode.md) | 22 | - [Use the window mode (`mm -tui`)](how-to/use-the-window-mode.md) |
| 23 | - [Navigate and refactor code with a language server (`lsp`)](how-to/navigate-code-with-lsp.md) | 23 | - [Navigate and refactor code with a language server (`lsp`)](how-to/navigate-code-with-lsp.md) |
| 24 | +- [Run a single prompt and exit (`-p`/`--prompt`)](how-to/run-a-single-prompt.md) | ||
| 24 | 25 | ||
| 25 | ## Reference — look it up | 26 | ## Reference — look it up |
| 26 | 27 | ||
added
docs/en/how-to/run-a-single-prompt.md +58 -0 | new file mode 100644 | ||
| @@ -0,0 +1,58 @@ | ||
| 1 | +# How to run a single prompt and exit | |
| 2 | + | |
| 3 | +This guide shows how to run mini-me with a single prompt and exit immediately after the response, without starting an interactive session. Useful for one-shot tasks, scripting, or quick queries. | |
| 4 | + | |
| 5 | +## Steps | |
| 6 | + | |
| 7 | +1. Run mini-me with the `-p` or `--prompt` flag and your prompt text: | |
| 8 | + | |
| 9 | + ```bash | |
| 10 | + mm -p "Create a README.md file with a project description" agent.yaml | |
| 11 | + ``` | |
| 12 | + | |
| 13 | + Or with the long form: | |
| 14 | + | |
| 15 | + ```bash | |
| 16 | + mm --prompt "What is the purpose of this project?" agent.yaml | |
| 17 | + ``` | |
| 18 | + | |
| 19 | +2. The agent executes the prompt, displays the tool call statistics and the response, then exits. | |
| 20 | + | |
| 21 | +## Variants | |
| 22 | + | |
| 23 | +- **Config file before or after the flag.** Both syntaxes work: | |
| 24 | + ```bash | |
| 25 | + mm -p "hello" agent.yaml | |
| 26 | + mm agent.yaml -p "hello" | |
| 27 | + ``` | |
| 28 | + | |
| 29 | +- **Use with different providers.** Works with any configuration file: | |
| 30 | + ```bash | |
| 31 | + mm -p "list files" agent.dmr.yaml | |
| 32 | + mm -p "explain this code" agent.llamacpp.yaml | |
| 33 | + ``` | |
| 34 | + | |
| 35 | +- **Capture the output.** The response prints to stdout, so you can pipe it: | |
| 36 | + ```bash | |
| 37 | + mm -p "generate a summary" agent.yaml > summary.txt | |
| 38 | + ``` | |
| 39 | + | |
| 40 | +- **Script it.** Use in shell scripts for automated tasks: | |
| 41 | + ```bash | |
| 42 | + #!/bin/sh | |
| 43 | + mm -p "fix the typos in this file" agent.yaml < input.txt | |
| 44 | + ``` | |
| 45 | + | |
| 46 | +## Notes | |
| 47 | + | |
| 48 | +- No banner is printed in prompt mode. | |
| 49 | +- No session is saved; the conversation does not persist. | |
| 50 | +- Tool calls are executed and displayed like in the line mode. | |
| 51 | +- The agent exits immediately after the response, even if tools were called. | |
| 52 | +- Not compatible with `-acp` (ACP mode) or `-tui` (window mode) — prompt mode takes precedence. | |
| 53 | + | |
| 54 | +## See also | |
| 55 | + | |
| 56 | +- Command line reference: [Reference — command line](../reference/cli.md) | |
| 57 | +- For interactive use: [How to use the window mode](use-the-window-mode.md) | |
| 58 | +- For editor integration: [Use mini-me from an editor (ACP)](use-from-an-editor.md) | |
| new file mode 100644 | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | +# How to run a single prompt and exit | ||
| 2 | + | ||
| 3 | +This guide shows how to run mini-me with a single prompt and exit immediately after the response, without starting an interactive session. Useful for one-shot tasks, scripting, or quick queries. | ||
| 4 | + | ||
| 5 | +## Steps | ||
| 6 | + | ||
| 7 | +1. Run mini-me with the `-p` or `--prompt` flag and your prompt text: | ||
| 8 | + | ||
| 9 | + ```bash | ||
| 10 | + mm -p "Create a README.md file with a project description" agent.yaml | ||
| 11 | + ``` | ||
| 12 | + | ||
| 13 | + Or with the long form: | ||
| 14 | + | ||
| 15 | + ```bash | ||
| 16 | + mm --prompt "What is the purpose of this project?" agent.yaml | ||
| 17 | + ``` | ||
| 18 | + | ||
| 19 | +2. The agent executes the prompt, displays the tool call statistics and the response, then exits. | ||
| 20 | + | ||
| 21 | +## Variants | ||
| 22 | + | ||
| 23 | +- **Config file before or after the flag.** Both syntaxes work: | ||
| 24 | + ```bash | ||
| 25 | + mm -p "hello" agent.yaml | ||
| 26 | + mm agent.yaml -p "hello" | ||
| 27 | + ``` | ||
| 28 | + | ||
| 29 | +- **Use with different providers.** Works with any configuration file: | ||
| 30 | + ```bash | ||
| 31 | + mm -p "list files" agent.dmr.yaml | ||
| 32 | + mm -p "explain this code" agent.llamacpp.yaml | ||
| 33 | + ``` | ||
| 34 | + | ||
| 35 | +- **Capture the output.** The response prints to stdout, so you can pipe it: | ||
| 36 | + ```bash | ||
| 37 | + mm -p "generate a summary" agent.yaml > summary.txt | ||
| 38 | + ``` | ||
| 39 | + | ||
| 40 | +- **Script it.** Use in shell scripts for automated tasks: | ||
| 41 | + ```bash | ||
| 42 | + #!/bin/sh | ||
| 43 | + mm -p "fix the typos in this file" agent.yaml < input.txt | ||
| 44 | + ``` | ||
| 45 | + | ||
| 46 | +## Notes | ||
| 47 | + | ||
| 48 | +- No banner is printed in prompt mode. | ||
| 49 | +- No session is saved; the conversation does not persist. | ||
| 50 | +- Tool calls are executed and displayed like in the line mode. | ||
| 51 | +- The agent exits immediately after the response, even if tools were called. | ||
| 52 | +- Not compatible with `-acp` (ACP mode) or `-tui` (window mode) — prompt mode takes precedence. | ||
| 53 | + | ||
| 54 | +## See also | ||
| 55 | + | ||
| 56 | +- Command line reference: [Reference — command line](../reference/cli.md) | ||
| 57 | +- For interactive use: [How to use the window mode](use-the-window-mode.md) | ||
| 58 | +- For editor integration: [Use mini-me from an editor (ACP)](use-from-an-editor.md) | ||
modified
docs/en/reference/cli.md +13 -1 | @@ -5,7 +5,7 @@ | ||
| 5 | 5 | ## Invocation |
| 6 | 6 | |
| 7 | 7 | ``` |
| 8 | -mm [-config <path>] [-acp] [-tui] [--version] [--about] [<path>] | |
| 8 | +mm [-config <path>] [-acp] [-tui] [-prompt <text>|-p <text>] [--version] [--about] [<path>] | |
| 9 | 9 | ``` |
| 10 | 10 | |
| 11 | 11 | | Element | Type | Default | Description | |
| @@ -14,6 +14,7 @@ mm [-config <path>] [-acp] [-tui] [--version] [--about] [<path>] | ||
| 14 | 14 | | `<path>` | positional | none | Same as `-config`, when `-config` is not given. A second positional argument is an error. | |
| 15 | 15 | | `-acp` | bool | `false` | Serve the Agent Client Protocol on stdin/stdout instead of the terminal REPL. | |
| 16 | 16 | | `-tui` | bool | `false` | Open the single-window mode (conversation above, input box below). Same effect as `tui: true` in the YAML; ignored with `-acp`. Falls back to the line mode when stdin or stdout is not a terminal. | |
| 17 | +| `-prompt <text>` / `-p <text>` | string | `""` | Run a single prompt and exit. The prompt text is required. Works with the config file before or after: `mm -p "hello" config.yaml` and `mm config.yaml -p "hello"` are both valid. No banner, no session persistence, no TUI/ACP. | | |
| 17 | 18 | | `--version` | bool | `false` | Print the version and exit, before the configuration is read. `-version` is the same flag. | |
| 18 | 19 | | `--about` | bool | `false` | Print what `mm` is — one screen: version, the three front ends, the tools, the model servers, where the project and the docs live — and exit, before the configuration is read. | |
| 19 | 20 | | `-h` | — | — | Print the flag usage and exit. | |
| @@ -103,6 +104,17 @@ mm v0.0.3 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/ | ||
| 103 | 104 | | Keys | See [Slash commands — window keys](slash-commands.md#window-mode-keys). | |
| 104 | 105 | | Mouse | Not captured at start-up, so the terminal's click-and-drag selection works. `F2` captures it (wheel scrolling; `Shift`+drag selects) and releases it again. | |
| 105 | 106 | |
| 107 | +## Prompt mode specifics | |
| 108 | + | |
| 109 | +| Aspect | Behaviour | | |
| 110 | +|--------|-----------| | |
| 111 | +| Execution | Runs a single generation cycle and exits. No REPL, no session persistence. | | |
| 112 | +| Output | Prints tool call statistics and the model's response, then exits. Same display as the line mode (⚙ commands, 📝 file ops, 📖 skills, 🔎 LSP calls). | | |
| 113 | +| Banner | Not printed. | | |
| 114 | +| Session | Not saved; no session directory used. | | |
| 115 | +| Config file | Can appear before or after the `-prompt`/`-p` flag: `mm -p "prompt" config.yaml` and `mm config.yaml -p "prompt"` both work. | | |
| 116 | +| Compatibility | Incompatible with `-acp` and `-tui`; prompt mode takes precedence and runs regardless. | | |
| 117 | + | |
| 106 | 118 | ## Exit codes |
| 107 | 119 | |
| 108 | 120 | | Code | Cause | |
| @@ -5,7 +5,7 @@ | |||
| 5 | ## Invocation | 5 | ## Invocation |
| 6 | 6 | ||
| 7 | ``` | 7 | ``` |
| 8 | -mm [-config <path>] [-acp] [-tui] [--version] [--about] [<path>] | 8 | +mm [-config <path>] [-acp] [-tui] [-prompt <text>|-p <text>] [--version] [--about] [<path>] |
| 9 | ``` | 9 | ``` |
| 10 | 10 | ||
| 11 | | Element | Type | Default | Description | | 11 | | Element | Type | Default | Description | |
| @@ -14,6 +14,7 @@ mm [-config <path>] [-acp] [-tui] [--version] [--about] [<path>] | |||
| 14 | | `<path>` | positional | none | Same as `-config`, when `-config` is not given. A second positional argument is an error. | | 14 | | `<path>` | positional | none | Same as `-config`, when `-config` is not given. A second positional argument is an error. | |
| 15 | | `-acp` | bool | `false` | Serve the Agent Client Protocol on stdin/stdout instead of the terminal REPL. | | 15 | | `-acp` | bool | `false` | Serve the Agent Client Protocol on stdin/stdout instead of the terminal REPL. | |
| 16 | | `-tui` | bool | `false` | Open the single-window mode (conversation above, input box below). Same effect as `tui: true` in the YAML; ignored with `-acp`. Falls back to the line mode when stdin or stdout is not a terminal. | | 16 | | `-tui` | bool | `false` | Open the single-window mode (conversation above, input box below). Same effect as `tui: true` in the YAML; ignored with `-acp`. Falls back to the line mode when stdin or stdout is not a terminal. | |
| 17 | +| `-prompt <text>` / `-p <text>` | string | `""` | Run a single prompt and exit. The prompt text is required. Works with the config file before or after: `mm -p "hello" config.yaml` and `mm config.yaml -p "hello"` are both valid. No banner, no session persistence, no TUI/ACP. | | ||
| 17 | | `--version` | bool | `false` | Print the version and exit, before the configuration is read. `-version` is the same flag. | | 18 | | `--version` | bool | `false` | Print the version and exit, before the configuration is read. `-version` is the same flag. | |
| 18 | | `--about` | bool | `false` | Print what `mm` is — one screen: version, the three front ends, the tools, the model servers, where the project and the docs live — and exit, before the configuration is read. | | 19 | | `--about` | bool | `false` | Print what `mm` is — one screen: version, the three front ends, the tools, the model servers, where the project and the docs live — and exit, before the configuration is read. | |
| 19 | | `-h` | — | — | Print the flag usage and exit. | | 20 | | `-h` | — | — | Print the flag usage and exit. | |
| @@ -103,6 +104,17 @@ mm v0.0.3 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/ | |||
| 103 | | Keys | See [Slash commands — window keys](slash-commands.md#window-mode-keys). | | 104 | | Keys | See [Slash commands — window keys](slash-commands.md#window-mode-keys). | |
| 104 | | Mouse | Not captured at start-up, so the terminal's click-and-drag selection works. `F2` captures it (wheel scrolling; `Shift`+drag selects) and releases it again. | | 105 | | Mouse | Not captured at start-up, so the terminal's click-and-drag selection works. `F2` captures it (wheel scrolling; `Shift`+drag selects) and releases it again. | |
| 105 | 106 | ||
| 107 | +## Prompt mode specifics | ||
| 108 | + | ||
| 109 | +| Aspect | Behaviour | | ||
| 110 | +|--------|-----------| | ||
| 111 | +| Execution | Runs a single generation cycle and exits. No REPL, no session persistence. | | ||
| 112 | +| Output | Prints tool call statistics and the model's response, then exits. Same display as the line mode (⚙ commands, 📝 file ops, 📖 skills, 🔎 LSP calls). | | ||
| 113 | +| Banner | Not printed. | | ||
| 114 | +| Session | Not saved; no session directory used. | | ||
| 115 | +| Config file | Can appear before or after the `-prompt`/`-p` flag: `mm -p "prompt" config.yaml` and `mm config.yaml -p "prompt"` both work. | | ||
| 116 | +| Compatibility | Incompatible with `-acp` and `-tui`; prompt mode takes precedence and runs regardless. | | ||
| 117 | + | ||
| 106 | ## Exit codes | 118 | ## Exit codes |
| 107 | 119 | ||
| 108 | | Code | Cause | | 120 | | Code | Cause | |
modified
docs/fr/README.md +1 -0 | @@ -21,6 +21,7 @@ Cette documentation est organisée selon les quatre quadrants [Diátaxis](https: | ||
| 21 | 21 | - [Conserver les sessions et les reprendre](how-to/keep-sessions.md) |
| 22 | 22 | - [Utiliser le mode fenêtre (`mm -tui`)](how-to/use-the-window-mode.md) |
| 23 | 23 | - [Naviguer et refactorer le code avec un serveur de langage (`lsp`)](how-to/navigate-code-with-lsp.md) |
| 24 | +- [Exécuter une invite unique et quitter (`-p`/`--prompt`)](how-to/executer-une-invite-unique.md) | |
| 24 | 25 | |
| 25 | 26 | ## Référence — consulter |
| 26 | 27 | |
| @@ -21,6 +21,7 @@ Cette documentation est organisée selon les quatre quadrants [Diátaxis](https: | |||
| 21 | - [Conserver les sessions et les reprendre](how-to/keep-sessions.md) | 21 | - [Conserver les sessions et les reprendre](how-to/keep-sessions.md) |
| 22 | - [Utiliser le mode fenêtre (`mm -tui`)](how-to/use-the-window-mode.md) | 22 | - [Utiliser le mode fenêtre (`mm -tui`)](how-to/use-the-window-mode.md) |
| 23 | - [Naviguer et refactorer le code avec un serveur de langage (`lsp`)](how-to/navigate-code-with-lsp.md) | 23 | - [Naviguer et refactorer le code avec un serveur de langage (`lsp`)](how-to/navigate-code-with-lsp.md) |
| 24 | +- [Exécuter une invite unique et quitter (`-p`/`--prompt`)](how-to/executer-une-invite-unique.md) | ||
| 24 | 25 | ||
| 25 | ## Référence — consulter | 26 | ## Référence — consulter |
| 26 | 27 | ||
added
docs/fr/how-to/executer-une-invite-unique.md +58 -0 | new file mode 100644 | ||
| @@ -0,0 +1,58 @@ | ||
| 1 | +# Exécuter une invite unique et quitter | |
| 2 | + | |
| 3 | +Ce guide montre comment lancer mini-me avec une seule invite et quitter immédiatement après la réponse, sans démarrer une session interactive. Utile pour les tâches ponctuelles, les scripts ou les requêtes rapides. | |
| 4 | + | |
| 5 | +## Étapes | |
| 6 | + | |
| 7 | +1. Lancez mini-me avec l'option `-p` ou `--prompt` et votre texte d'invite : | |
| 8 | + | |
| 9 | + ```bash | |
| 10 | + mm -p "Créez un fichier README.md avec une description de projet" agent.yaml | |
| 11 | + ``` | |
| 12 | + | |
| 13 | + Ou avec la forme longue : | |
| 14 | + | |
| 15 | + ```bash | |
| 16 | + mm --prompt "Quel est l'objectif de ce projet ?" agent.yaml | |
| 17 | + ``` | |
| 18 | + | |
| 19 | +2. L'agent exécute l'invite, affiche les statistiques d'appels d'outils et la réponse, puis quitte. | |
| 20 | + | |
| 21 | +## Variantes | |
| 22 | + | |
| 23 | +- **Fichier de config avant ou après le flag.** Les deux syntaxes fonctionnent : | |
| 24 | + ```bash | |
| 25 | + mm -p "bonjour" agent.yaml | |
| 26 | + mm agent.yaml -p "bonjour" | |
| 27 | + ``` | |
| 28 | + | |
| 29 | +- **Utilisation avec différents fournisseurs.** Fonctionne avec n'importe quel fichier de configuration : | |
| 30 | + ```bash | |
| 31 | + mm -p "listez les fichiers" agent.dmr.yaml | |
| 32 | + mm -p "expliquez ce code" agent.llamacpp.yaml | |
| 33 | + ``` | |
| 34 | + | |
| 35 | +- **Capturer la sortie.** La réponse s'affiche sur stdout, donc vous pouvez la rediriger : | |
| 36 | + ```bash | |
| 37 | + mm -p "générez un résumé" agent.yaml > resume.txt | |
| 38 | + ``` | |
| 39 | + | |
| 40 | +- **Script.** Utilisez dans des scripts shell pour des tâches automatisées : | |
| 41 | + ```bash | |
| 42 | + #!/bin/sh | |
| 43 | + mm -p "corrigez les fautes dans ce fichier" agent.yaml < input.txt | |
| 44 | + ``` | |
| 45 | + | |
| 46 | +## Remarques | |
| 47 | + | |
| 48 | +- Aucune bannière n'est affichée en mode invite. | |
| 49 | +- Aucune session n'est sauvegardée ; la conversation ne persiste pas. | |
| 50 | +- Les appels d'outils sont exécutés et affichés comme en mode ligne. | |
| 51 | +- L'agent quitte immédiatement après la réponse, même si des outils ont été appelés. | |
| 52 | +- Incompatible avec `-acp` (mode ACP) ou `-tui` (mode fenêtre) — le mode invite prend la priorité. | |
| 53 | + | |
| 54 | +## Voir aussi | |
| 55 | + | |
| 56 | +- Référence de la ligne de commande : [Référence — ligne de commande](../reference/cli.md) | |
| 57 | +- Pour une utilisation interactive : [Utiliser le mode fenêtre](use-the-window-mode.md) | |
| 58 | +- Pour l'intégration à un éditeur : [Utiliser mini-me depuis un éditeur (ACP)](use-from-an-editor.md) | |
| new file mode 100644 | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | +# Exécuter une invite unique et quitter | ||
| 2 | + | ||
| 3 | +Ce guide montre comment lancer mini-me avec une seule invite et quitter immédiatement après la réponse, sans démarrer une session interactive. Utile pour les tâches ponctuelles, les scripts ou les requêtes rapides. | ||
| 4 | + | ||
| 5 | +## Étapes | ||
| 6 | + | ||
| 7 | +1. Lancez mini-me avec l'option `-p` ou `--prompt` et votre texte d'invite : | ||
| 8 | + | ||
| 9 | + ```bash | ||
| 10 | + mm -p "Créez un fichier README.md avec une description de projet" agent.yaml | ||
| 11 | + ``` | ||
| 12 | + | ||
| 13 | + Ou avec la forme longue : | ||
| 14 | + | ||
| 15 | + ```bash | ||
| 16 | + mm --prompt "Quel est l'objectif de ce projet ?" agent.yaml | ||
| 17 | + ``` | ||
| 18 | + | ||
| 19 | +2. L'agent exécute l'invite, affiche les statistiques d'appels d'outils et la réponse, puis quitte. | ||
| 20 | + | ||
| 21 | +## Variantes | ||
| 22 | + | ||
| 23 | +- **Fichier de config avant ou après le flag.** Les deux syntaxes fonctionnent : | ||
| 24 | + ```bash | ||
| 25 | + mm -p "bonjour" agent.yaml | ||
| 26 | + mm agent.yaml -p "bonjour" | ||
| 27 | + ``` | ||
| 28 | + | ||
| 29 | +- **Utilisation avec différents fournisseurs.** Fonctionne avec n'importe quel fichier de configuration : | ||
| 30 | + ```bash | ||
| 31 | + mm -p "listez les fichiers" agent.dmr.yaml | ||
| 32 | + mm -p "expliquez ce code" agent.llamacpp.yaml | ||
| 33 | + ``` | ||
| 34 | + | ||
| 35 | +- **Capturer la sortie.** La réponse s'affiche sur stdout, donc vous pouvez la rediriger : | ||
| 36 | + ```bash | ||
| 37 | + mm -p "générez un résumé" agent.yaml > resume.txt | ||
| 38 | + ``` | ||
| 39 | + | ||
| 40 | +- **Script.** Utilisez dans des scripts shell pour des tâches automatisées : | ||
| 41 | + ```bash | ||
| 42 | + #!/bin/sh | ||
| 43 | + mm -p "corrigez les fautes dans ce fichier" agent.yaml < input.txt | ||
| 44 | + ``` | ||
| 45 | + | ||
| 46 | +## Remarques | ||
| 47 | + | ||
| 48 | +- Aucune bannière n'est affichée en mode invite. | ||
| 49 | +- Aucune session n'est sauvegardée ; la conversation ne persiste pas. | ||
| 50 | +- Les appels d'outils sont exécutés et affichés comme en mode ligne. | ||
| 51 | +- L'agent quitte immédiatement après la réponse, même si des outils ont été appelés. | ||
| 52 | +- Incompatible avec `-acp` (mode ACP) ou `-tui` (mode fenêtre) — le mode invite prend la priorité. | ||
| 53 | + | ||
| 54 | +## Voir aussi | ||
| 55 | + | ||
| 56 | +- Référence de la ligne de commande : [Référence — ligne de commande](../reference/cli.md) | ||
| 57 | +- Pour une utilisation interactive : [Utiliser le mode fenêtre](use-the-window-mode.md) | ||
| 58 | +- Pour l'intégration à un éditeur : [Utiliser mini-me depuis un éditeur (ACP)](use-from-an-editor.md) | ||
modified
docs/fr/reference/cli.md +13 -1 | @@ -5,7 +5,7 @@ | ||
| 5 | 5 | ## Invocation |
| 6 | 6 | |
| 7 | 7 | ``` |
| 8 | -mm [-config <chemin>] [-acp] [-tui] [--version] [--about] [<chemin>] | |
| 8 | +mm [-config <chemin>] [-acp] [-tui] [-prompt <texte>|-p <texte>] [--version] [--about] [<chemin>] | |
| 9 | 9 | ``` |
| 10 | 10 | |
| 11 | 11 | | Élément | Type | Défaut | Description | |
| @@ -14,6 +14,7 @@ mm [-config <chemin>] [-acp] [-tui] [--version] [--about] [<chemin>] | ||
| 14 | 14 | | `<chemin>` | positionnel | aucun | Équivalent de `-config` quand `-config` n'est pas donné. Un second argument positionnel est une erreur. | |
| 15 | 15 | | `-acp` | booléen | `false` | Sert l'Agent Client Protocol sur stdin/stdout au lieu du REPL du terminal. | |
| 16 | 16 | | `-tui` | booléen | `false` | Ouvre le mode fenêtre unique (conversation en haut, zone de saisie en bas). Même effet que `tui: true` dans le YAML ; ignoré avec `-acp`. Retombe sur le mode ligne quand stdin ou stdout n'est pas un terminal. | |
| 17 | +| `-prompt <texte>` / `-p <texte>` | chaîne | `""` | Exécute une seule invite et quitte. Le texte de l'invite est obligatoire. Fonctionne avec le fichier de config avant ou après : `mm -p "bonjour" config.yaml` et `mm config.yaml -p "bonjour"` sont tous deux valides. Pas de bannière, pas de persistance de session, pas de TUI/ACP. | | |
| 17 | 18 | | `--version` | bool | `false` | Affiche la version et quitte, avant la lecture de la configuration. `-version` est la même option. | |
| 18 | 19 | | `--about` | bool | `false` | Affiche ce qu'est `mm` — un écran : version, les trois façades, les outils, les serveurs de modèles, où vivent le projet et la documentation — puis quitte, avant la lecture de la configuration. | |
| 19 | 20 | | `-h` | — | — | Affiche l'usage des options et quitte. | |
| @@ -103,6 +104,17 @@ mm v0.0.3 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/ | ||
| 103 | 104 | | Touches | Voir [Commandes slash — touches du mode fenêtre](slash-commands.md#touches-du-mode-fenêtre). | |
| 104 | 105 | | Souris | Non capturée au démarrage, donc le cliquer-glisser du terminal sélectionne du texte. `F2` la capture (défilement à la molette ; `Maj`+glisser sélectionne) puis la rend. | |
| 105 | 106 | |
| 107 | +## Spécificités du mode invite | |
| 108 | + | |
| 109 | +| Aspect | Comportement | | |
| 110 | +|--------|--------------| | |
| 111 | +| Exécution | Exécute un seul cycle de génération puis quitte. Pas de REPL, pas de persistance de session. | | |
| 112 | +| Sortie | Affiche les statistiques d'appels d'outils et la réponse du modèle, puis quitte. Même affichage que le mode ligne (⚙ commandes, 📝 opérations sur fichiers, 📖 skills, 🔎 appels LSP). | | |
| 113 | +| Bannière | Non affichée. | | |
| 114 | +| Session | Non sauvegardée ; aucun répertoire de sessions utilisé. | | |
| 115 | +| Fichier de config | Peut apparaître avant ou après le flag `-prompt`/`-p` : `mm -p "prompt" config.yaml` et `mm config.yaml -p "prompt"` fonctionnent tous deux. | | |
| 116 | +| Compatibilité | Incompatible avec `-acp` et `-tui` ; le mode invite prend la priorité et s'exécute dans tous les cas. | | |
| 117 | + | |
| 106 | 118 | ## Codes de sortie |
| 107 | 119 | |
| 108 | 120 | | Code | Cause | |
| @@ -5,7 +5,7 @@ | |||
| 5 | ## Invocation | 5 | ## Invocation |
| 6 | 6 | ||
| 7 | ``` | 7 | ``` |
| 8 | -mm [-config <chemin>] [-acp] [-tui] [--version] [--about] [<chemin>] | 8 | +mm [-config <chemin>] [-acp] [-tui] [-prompt <texte>|-p <texte>] [--version] [--about] [<chemin>] |
| 9 | ``` | 9 | ``` |
| 10 | 10 | ||
| 11 | | Élément | Type | Défaut | Description | | 11 | | Élément | Type | Défaut | Description | |
| @@ -14,6 +14,7 @@ mm [-config <chemin>] [-acp] [-tui] [--version] [--about] [<chemin>] | |||
| 14 | | `<chemin>` | positionnel | aucun | Équivalent de `-config` quand `-config` n'est pas donné. Un second argument positionnel est une erreur. | | 14 | | `<chemin>` | positionnel | aucun | Équivalent de `-config` quand `-config` n'est pas donné. Un second argument positionnel est une erreur. | |
| 15 | | `-acp` | booléen | `false` | Sert l'Agent Client Protocol sur stdin/stdout au lieu du REPL du terminal. | | 15 | | `-acp` | booléen | `false` | Sert l'Agent Client Protocol sur stdin/stdout au lieu du REPL du terminal. | |
| 16 | | `-tui` | booléen | `false` | Ouvre le mode fenêtre unique (conversation en haut, zone de saisie en bas). Même effet que `tui: true` dans le YAML ; ignoré avec `-acp`. Retombe sur le mode ligne quand stdin ou stdout n'est pas un terminal. | | 16 | | `-tui` | booléen | `false` | Ouvre le mode fenêtre unique (conversation en haut, zone de saisie en bas). Même effet que `tui: true` dans le YAML ; ignoré avec `-acp`. Retombe sur le mode ligne quand stdin ou stdout n'est pas un terminal. | |
| 17 | +| `-prompt <texte>` / `-p <texte>` | chaîne | `""` | Exécute une seule invite et quitte. Le texte de l'invite est obligatoire. Fonctionne avec le fichier de config avant ou après : `mm -p "bonjour" config.yaml` et `mm config.yaml -p "bonjour"` sont tous deux valides. Pas de bannière, pas de persistance de session, pas de TUI/ACP. | | ||
| 17 | | `--version` | bool | `false` | Affiche la version et quitte, avant la lecture de la configuration. `-version` est la même option. | | 18 | | `--version` | bool | `false` | Affiche la version et quitte, avant la lecture de la configuration. `-version` est la même option. | |
| 18 | | `--about` | bool | `false` | Affiche ce qu'est `mm` — un écran : version, les trois façades, les outils, les serveurs de modèles, où vivent le projet et la documentation — puis quitte, avant la lecture de la configuration. | | 19 | | `--about` | bool | `false` | Affiche ce qu'est `mm` — un écran : version, les trois façades, les outils, les serveurs de modèles, où vivent le projet et la documentation — puis quitte, avant la lecture de la configuration. | |
| 19 | | `-h` | — | — | Affiche l'usage des options et quitte. | | 20 | | `-h` | — | — | Affiche l'usage des options et quitte. | |
| @@ -103,6 +104,17 @@ mm v0.0.3 | config: agent.llamacpp.yaml | provider: llamacpp | model: jetbrains/ | |||
| 103 | | Touches | Voir [Commandes slash — touches du mode fenêtre](slash-commands.md#touches-du-mode-fenêtre). | | 104 | | Touches | Voir [Commandes slash — touches du mode fenêtre](slash-commands.md#touches-du-mode-fenêtre). | |
| 104 | | Souris | Non capturée au démarrage, donc le cliquer-glisser du terminal sélectionne du texte. `F2` la capture (défilement à la molette ; `Maj`+glisser sélectionne) puis la rend. | | 105 | | Souris | Non capturée au démarrage, donc le cliquer-glisser du terminal sélectionne du texte. `F2` la capture (défilement à la molette ; `Maj`+glisser sélectionne) puis la rend. | |
| 105 | 106 | ||
| 107 | +## Spécificités du mode invite | ||
| 108 | + | ||
| 109 | +| Aspect | Comportement | | ||
| 110 | +|--------|--------------| | ||
| 111 | +| Exécution | Exécute un seul cycle de génération puis quitte. Pas de REPL, pas de persistance de session. | | ||
| 112 | +| Sortie | Affiche les statistiques d'appels d'outils et la réponse du modèle, puis quitte. Même affichage que le mode ligne (⚙ commandes, 📝 opérations sur fichiers, 📖 skills, 🔎 appels LSP). | | ||
| 113 | +| Bannière | Non affichée. | | ||
| 114 | +| Session | Non sauvegardée ; aucun répertoire de sessions utilisé. | | ||
| 115 | +| Fichier de config | Peut apparaître avant ou après le flag `-prompt`/`-p` : `mm -p "prompt" config.yaml` et `mm config.yaml -p "prompt"` fonctionnent tous deux. | | ||
| 116 | +| Compatibilité | Incompatible avec `-acp` et `-tui` ; le mode invite prend la priorité et s'exécute dans tous les cas. | | ||
| 117 | + | ||
| 106 | ## Codes de sortie | 118 | ## Codes de sortie |
| 107 | 119 | ||
| 108 | | Code | Cause | | 120 | | Code | Cause | |
modified
internal/agent/agent.go +54 -0 | @@ -509,3 +509,57 @@ func (l *loop) historyCommand(input string, messages []*ai.Message) ([]*ai.Messa | ||
| 509 | 509 | } |
| 510 | 510 | return messages, true |
| 511 | 511 | } |
| 512 | + | |
| 513 | +// RunPrompt executes a single prompt and displays the result, then exits. | |
| 514 | +// This is the one-shot mode for running a single prompt without interaction. | |
| 515 | +func RunPrompt(ctx context.Context, e *engine.Engine, system string, tools []ai.ToolRef, d *detector.LoopDetector, prompt string) { | |
| 516 | + messages := session.Fresh(system) | |
| 517 | + | |
| 518 | + // Add the user's prompt to the history | |
| 519 | + messages = append(messages, ai.NewUserTextMessage(prompt)) | |
| 520 | + before := len(messages) | |
| 521 | + | |
| 522 | + fmt.Println() | |
| 523 | + | |
| 524 | + // Execute generation | |
| 525 | + resp, history, err := e.Generate(ctx, messages, tools) | |
| 526 | + if err != nil { | |
| 527 | + fmt.Printf("⚠️ Generation failed: %v\n", err) | |
| 528 | + return | |
| 529 | + } | |
| 530 | + | |
| 531 | + // Process and display the result | |
| 532 | + messages = session.AfterTurn(messages, before, resp, history, err) | |
| 533 | + | |
| 534 | + // Display command stats like the regular mode | |
| 535 | + turn := history[min(before, len(history)):] | |
| 536 | + cmds := engine.CommandList(turn) | |
| 537 | + ops := engine.FileOps(turn) | |
| 538 | + line := fmt.Sprintf("⚙ %d command(s)", len(cmds)) | |
| 539 | + if len(ops) > 0 { | |
| 540 | + line += fmt.Sprintf(" · 📝 %d file op(s)", len(ops)) | |
| 541 | + } | |
| 542 | + if engine.SkillsAvailable() { | |
| 543 | + line += fmt.Sprintf(" · 📖 %d skill(s)", engine.Skills(turn)) | |
| 544 | + } | |
| 545 | + if k := engine.LSPCalls(turn); k > 0 { | |
| 546 | + line += fmt.Sprintf(" · 🔎 %d lsp call(s)", k) | |
| 547 | + } | |
| 548 | + if spinner.Styled() { | |
| 549 | + fmt.Printf("\033[2m%s\033[0m\n", line) | |
| 550 | + } else { | |
| 551 | + fmt.Println(line) | |
| 552 | + } | |
| 553 | + if config.Cfg.DisplayCommands { | |
| 554 | + printCommands(cmds) | |
| 555 | + printCommands(ops) | |
| 556 | + } | |
| 557 | + | |
| 558 | + // Display the response | |
| 559 | + if resp != nil && resp.Message != nil { | |
| 560 | + for _, part := range resp.Message.Content { | |
| 561 | + fmt.Print(part.Text) | |
| 562 | + } | |
| 563 | + fmt.Println() | |
| 564 | + } | |
| 565 | +} | |
| @@ -509,3 +509,57 @@ func (l *loop) historyCommand(input string, messages []*ai.Message) ([]*ai.Messa | |||
| 509 | } | 509 | } |
| 510 | return messages, true | 510 | return messages, true |
| 511 | } | 511 | } |
| 512 | + | ||
| 513 | +// RunPrompt executes a single prompt and displays the result, then exits. | ||
| 514 | +// This is the one-shot mode for running a single prompt without interaction. | ||
| 515 | +func RunPrompt(ctx context.Context, e *engine.Engine, system string, tools []ai.ToolRef, d *detector.LoopDetector, prompt string) { | ||
| 516 | + messages := session.Fresh(system) | ||
| 517 | + | ||
| 518 | + // Add the user's prompt to the history | ||
| 519 | + messages = append(messages, ai.NewUserTextMessage(prompt)) | ||
| 520 | + before := len(messages) | ||
| 521 | + | ||
| 522 | + fmt.Println() | ||
| 523 | + | ||
| 524 | + // Execute generation | ||
| 525 | + resp, history, err := e.Generate(ctx, messages, tools) | ||
| 526 | + if err != nil { | ||
| 527 | + fmt.Printf("⚠️ Generation failed: %v\n", err) | ||
| 528 | + return | ||
| 529 | + } | ||
| 530 | + | ||
| 531 | + // Process and display the result | ||
| 532 | + messages = session.AfterTurn(messages, before, resp, history, err) | ||
| 533 | + | ||
| 534 | + // Display command stats like the regular mode | ||
| 535 | + turn := history[min(before, len(history)):] | ||
| 536 | + cmds := engine.CommandList(turn) | ||
| 537 | + ops := engine.FileOps(turn) | ||
| 538 | + line := fmt.Sprintf("⚙ %d command(s)", len(cmds)) | ||
| 539 | + if len(ops) > 0 { | ||
| 540 | + line += fmt.Sprintf(" · 📝 %d file op(s)", len(ops)) | ||
| 541 | + } | ||
| 542 | + if engine.SkillsAvailable() { | ||
| 543 | + line += fmt.Sprintf(" · 📖 %d skill(s)", engine.Skills(turn)) | ||
| 544 | + } | ||
| 545 | + if k := engine.LSPCalls(turn); k > 0 { | ||
| 546 | + line += fmt.Sprintf(" · 🔎 %d lsp call(s)", k) | ||
| 547 | + } | ||
| 548 | + if spinner.Styled() { | ||
| 549 | + fmt.Printf("\033[2m%s\033[0m\n", line) | ||
| 550 | + } else { | ||
| 551 | + fmt.Println(line) | ||
| 552 | + } | ||
| 553 | + if config.Cfg.DisplayCommands { | ||
| 554 | + printCommands(cmds) | ||
| 555 | + printCommands(ops) | ||
| 556 | + } | ||
| 557 | + | ||
| 558 | + // Display the response | ||
| 559 | + if resp != nil && resp.Message != nil { | ||
| 560 | + for _, part := range resp.Message.Content { | ||
| 561 | + fmt.Print(part.Text) | ||
| 562 | + } | ||
| 563 | + fmt.Println() | ||
| 564 | + } | ||
| 565 | +} | ||
modified
main.go +37 -0 | @@ -64,12 +64,41 @@ func main() { | ||
| 64 | 64 | // |
| 65 | 65 | // The flag package gives us "-h" for free; a second argument is a typo, and |
| 66 | 66 | // saying so is better than ignoring it. |
| 67 | + | |
| 68 | + // Handle --prompt/-p flag which can appear after the config file argument | |
| 69 | + // We manually extract it before flag.Parse() so both orders work: | |
| 70 | + // mm --prompt "hello" agent.yaml AND mm agent.yaml --prompt "hello" | |
| 71 | + promptArg := "" | |
| 72 | + remainingArgs := []string{} | |
| 73 | + for i := 1; i < len(os.Args); i++ { | |
| 74 | + arg := os.Args[i] | |
| 75 | + if arg == "--prompt" || arg == "-p" { | |
| 76 | + if i+1 < len(os.Args) { | |
| 77 | + promptArg = os.Args[i+1] | |
| 78 | + i++ // skip the next arg (the prompt value) | |
| 79 | + } else { | |
| 80 | + promptArg = "" | |
| 81 | + } | |
| 82 | + } else { | |
| 83 | + remainingArgs = append(remainingArgs, arg) | |
| 84 | + } | |
| 85 | + } | |
| 86 | + // Replace os.Args for flag.Parse() | |
| 87 | + os.Args = append([]string{os.Args[0]}, remainingArgs...) | |
| 88 | + | |
| 67 | 89 | configPath := flag.String("config", "", "path to the YAML config file (default: $AGENT_CONFIG, then ./agent.yaml)") |
| 68 | 90 | acpMode := flag.Bool("acp", false, "serve the Agent Client Protocol on stdio (for Zed, JetBrains, Neovim…) instead of the terminal REPL") |
| 69 | 91 | tuiMode := flag.Bool("tui", false, "open the single-window mode (conversation above, input box below); falls back to the line mode when stdout is not a terminal") |
| 92 | + promptMode := flag.String("prompt", "", "run a single prompt and exit") | |
| 93 | + flag.StringVar(promptMode, "p", "", "shorthand for --prompt") | |
| 70 | 94 | showVersion := flag.Bool("version", false, "print the version and exit") |
| 71 | 95 | showAbout := flag.Bool("about", false, "print what mm is, and exit") |
| 72 | 96 | flag.Parse() |
| 97 | + | |
| 98 | + // If prompt was extracted manually, use it (overrides flag value) | |
| 99 | + if promptArg != "" { | |
| 100 | + *promptMode = promptArg | |
| 101 | + } | |
| 73 | 102 | // Answered before anything can go wrong: asking which mm this is must |
| 74 | 103 | // work without a config file, without a model server, and in a directory |
| 75 | 104 | // mm knows nothing about. Straight to stdout, not ui.Out — this is the |
| @@ -141,6 +170,14 @@ func main() { | ||
| 141 | 170 | if path == "" { |
| 142 | 171 | path = "built-in defaults" |
| 143 | 172 | } |
| 173 | + | |
| 174 | + // Handle prompt mode: run a single prompt and exit | |
| 175 | + if *promptMode != "" { | |
| 176 | + // In prompt mode, no banner, no session persistence | |
| 177 | + agent.RunPrompt(ctx, e, config.Cfg.System, agentTools, loopDetector, *promptMode) | |
| 178 | + return | |
| 179 | + } | |
| 180 | + | |
| 144 | 181 | printBanner(ctx, e, path, set) |
| 145 | 182 | |
| 146 | 183 | // Three front ends, one wiring: everything above — config, engine, tools, |
| @@ -64,12 +64,41 @@ func main() { | |||
| 64 | // | 64 | // |
| 65 | // The flag package gives us "-h" for free; a second argument is a typo, and | 65 | // The flag package gives us "-h" for free; a second argument is a typo, and |
| 66 | // saying so is better than ignoring it. | 66 | // saying so is better than ignoring it. |
| 67 | + | ||
| 68 | + // Handle --prompt/-p flag which can appear after the config file argument | ||
| 69 | + // We manually extract it before flag.Parse() so both orders work: | ||
| 70 | + // mm --prompt "hello" agent.yaml AND mm agent.yaml --prompt "hello" | ||
| 71 | + promptArg := "" | ||
| 72 | + remainingArgs := []string{} | ||
| 73 | + for i := 1; i < len(os.Args); i++ { | ||
| 74 | + arg := os.Args[i] | ||
| 75 | + if arg == "--prompt" || arg == "-p" { | ||
| 76 | + if i+1 < len(os.Args) { | ||
| 77 | + promptArg = os.Args[i+1] | ||
| 78 | + i++ // skip the next arg (the prompt value) | ||
| 79 | + } else { | ||
| 80 | + promptArg = "" | ||
| 81 | + } | ||
| 82 | + } else { | ||
| 83 | + remainingArgs = append(remainingArgs, arg) | ||
| 84 | + } | ||
| 85 | + } | ||
| 86 | + // Replace os.Args for flag.Parse() | ||
| 87 | + os.Args = append([]string{os.Args[0]}, remainingArgs...) | ||
| 88 | + | ||
| 67 | configPath := flag.String("config", "", "path to the YAML config file (default: $AGENT_CONFIG, then ./agent.yaml)") | 89 | configPath := flag.String("config", "", "path to the YAML config file (default: $AGENT_CONFIG, then ./agent.yaml)") |
| 68 | acpMode := flag.Bool("acp", false, "serve the Agent Client Protocol on stdio (for Zed, JetBrains, Neovim…) instead of the terminal REPL") | 90 | acpMode := flag.Bool("acp", false, "serve the Agent Client Protocol on stdio (for Zed, JetBrains, Neovim…) instead of the terminal REPL") |
| 69 | tuiMode := flag.Bool("tui", false, "open the single-window mode (conversation above, input box below); falls back to the line mode when stdout is not a terminal") | 91 | tuiMode := flag.Bool("tui", false, "open the single-window mode (conversation above, input box below); falls back to the line mode when stdout is not a terminal") |
| 92 | + promptMode := flag.String("prompt", "", "run a single prompt and exit") | ||
| 93 | + flag.StringVar(promptMode, "p", "", "shorthand for --prompt") | ||
| 70 | showVersion := flag.Bool("version", false, "print the version and exit") | 94 | showVersion := flag.Bool("version", false, "print the version and exit") |
| 71 | showAbout := flag.Bool("about", false, "print what mm is, and exit") | 95 | showAbout := flag.Bool("about", false, "print what mm is, and exit") |
| 72 | flag.Parse() | 96 | flag.Parse() |
| 97 | + | ||
| 98 | + // If prompt was extracted manually, use it (overrides flag value) | ||
| 99 | + if promptArg != "" { | ||
| 100 | + *promptMode = promptArg | ||
| 101 | + } | ||
| 73 | // Answered before anything can go wrong: asking which mm this is must | 102 | // Answered before anything can go wrong: asking which mm this is must |
| 74 | // work without a config file, without a model server, and in a directory | 103 | // work without a config file, without a model server, and in a directory |
| 75 | // mm knows nothing about. Straight to stdout, not ui.Out — this is the | 104 | // mm knows nothing about. Straight to stdout, not ui.Out — this is the |
| @@ -141,6 +170,14 @@ func main() { | |||
| 141 | if path == "" { | 170 | if path == "" { |
| 142 | path = "built-in defaults" | 171 | path = "built-in defaults" |
| 143 | } | 172 | } |
| 173 | + | ||
| 174 | + // Handle prompt mode: run a single prompt and exit | ||
| 175 | + if *promptMode != "" { | ||
| 176 | + // In prompt mode, no banner, no session persistence | ||
| 177 | + agent.RunPrompt(ctx, e, config.Cfg.System, agentTools, loopDetector, *promptMode) | ||
| 178 | + return | ||
| 179 | + } | ||
| 180 | + | ||
| 144 | printBanner(ctx, e, path, set) | 181 | printBanner(ctx, e, path, set) |
| 145 | 182 | ||
| 146 | // Three front ends, one wiring: everything above — config, engine, tools, | 183 | // Three front ends, one wiring: everything above — config, engine, tools, |