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

k33g committed 2026-10-21T14:53:21+02:00 Browse files
d56bc20 parent: a38f300
modified .tickets/issues/0117-make-possible-the-usage-of-mm-tui-like-mm-tui-an.yaml +30 -4
@@ -1,14 +1,40 @@
11 # Managed by IssueSpec. Hand edits are welcome; keep the schema valid.
22 id: 117
33 title: make possible the usage of mm tui like mm --tui and mm acp like mm --acp
4-state: open
4+state: closed
55 author:
66 name: k33g
77 email: ph.charriere@gmail.com
88 createdAt: 2026-10-21T11:39:39.289Z
9-updatedAt: 2026-10-21T11:44:38.778Z
9+updatedAt: 2026-10-21T23:45:00.000Z
1010 labels: []
1111 milestone: v0.9.0
12-body: ""
12+body: |
13+ `mm tui` should do what `mm -tui` does, and `mm acp` what `mm -acp` does —
14+ the modes as words, like `mm init`.
1315 tasks: []
14-comments: []
16+comments:
17+ - id: 1
18+ author:
19+ name: k33g
20+ email: ph.charriere@gmail.com
21+ createdAt: 2026-10-21T23:30:00.000Z
22+ body: |
23+ Done (2026-10-21, on main, uncommitted).
24+ - `mm --tui` and `mm --acp` already worked: Go's flag package takes
25+ `-x` and `--x` alike. What was missing was the words.
26+ - main.go: modeWordAsFlag rewrites a FIRST argument `tui` / `acp` into
27+ `-tui` / `-acp` before the flags are read, so the rest of main is
28+ unchanged and every other flag still works (`mm tui -config a.yaml`,
29+ `mm acp agent.yaml`). Anywhere else the word is not special:
30+ `mm agent.yaml tui` still names two config files. A config file
31+ called tui or acp is now reached as ./tui or with -config (same
32+ rule as init since ticket 97).
33+ - -h: both flags say "(same as: mm tui)" / "(same as: mm acp)"
34+ (backticks would have been read by the flag package as the
35+ argument's name).
36+ - Test: TestModeWordAsFlag (init_assemble_test.go). Live: `mm acp`
37+ and `mm -acp` give the same initialize answer; `mm tui` piped falls
38+ back to the line mode like `mm -tui`.
39+ - Docs EN+FR: reference/cli (invocation lines, -acp, -tui and <path>
40+ rows).
@@ -1,14 +1,40 @@
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: 1172 id: 117
3 title: make possible the usage of mm tui like mm --tui and mm acp like mm --acp3 title: make possible the usage of mm tui like mm --tui and mm acp like mm --acp
4-state: open4+state: closed
5 author:5 author:
6 name: k33g6 name: k33g
7 email: ph.charriere@gmail.com7 email: ph.charriere@gmail.com
8 createdAt: 2026-10-21T11:39:39.289Z8 createdAt: 2026-10-21T11:39:39.289Z
9-updatedAt: 2026-10-21T11:44:38.778Z9+updatedAt: 2026-10-21T23:45:00.000Z
10 labels: []10 labels: []
11 milestone: v0.9.011 milestone: v0.9.0
12-body: ""12+body: |
13+ `mm tui` should do what `mm -tui` does, and `mm acp` what `mm -acp` does —
14+ the modes as words, like `mm init`.
13 tasks: []15 tasks: []
14-comments: []16+comments:
17+ - id: 1
18+ author:
19+ name: k33g
20+ email: ph.charriere@gmail.com
21+ createdAt: 2026-10-21T23:30:00.000Z
22+ body: |
23+ Done (2026-10-21, on main, uncommitted).
24+ - `mm --tui` and `mm --acp` already worked: Go's flag package takes
25+ `-x` and `--x` alike. What was missing was the words.
26+ - main.go: modeWordAsFlag rewrites a FIRST argument `tui` / `acp` into
27+ `-tui` / `-acp` before the flags are read, so the rest of main is
28+ unchanged and every other flag still works (`mm tui -config a.yaml`,
29+ `mm acp agent.yaml`). Anywhere else the word is not special:
30+ `mm agent.yaml tui` still names two config files. A config file
31+ called tui or acp is now reached as ./tui or with -config (same
32+ rule as init since ticket 97).
33+ - -h: both flags say "(same as: mm tui)" / "(same as: mm acp)"
34+ (backticks would have been read by the flag package as the
35+ argument's name).
36+ - Test: TestModeWordAsFlag (init_assemble_test.go). Live: `mm acp`
37+ and `mm -acp` give the same initialize answer; `mm tui` piped falls
38+ back to the line mode like `mm -tui`.
39+ - Docs EN+FR: reference/cli (invocation lines, -acp, -tui and <path>
40+ rows).
modified docs/en/reference/cli.md +5 -3
@@ -9,14 +9,16 @@ mm [-config <path>] [-acp] [-tui] [-prompt <text>|-p <text>] [--version] [--abou
99 mm [-config <path>] --ask <agent> [-p <question>] (question on stdin when -p is absent)
1010 mm [-config <path>] --ask-with-context <agent> [-p <question>] (context on stdin)
1111 mm init [flags] (write a new agent.yaml; also mm --init)
12+mm tui [<path>] [flags] (same as mm -tui)
13+mm acp [<path>] [flags] (same as mm -acp)
1214 ```
1315
1416 | Element | Type | Default | Description |
1517 |---------|------|---------|-------------|
1618 | `-config <path>` | string | `""` | Path of the YAML configuration file. |
17-| `<path>` | positional | none | Same as `-config`, when `-config` is not given. A second positional argument is an error. |
18-| `-acp` | bool | `false` | Serve the Agent Client Protocol on stdin/stdout instead of the terminal REPL. |
19-| `-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. |
19+| `<path>` | positional | none | Same as `-config`, when `-config` is not given. A second positional argument is an error. A first argument `init`, `tui` or `acp` is a mode word, not a path: a configuration file with one of these names is given as `./tui` or with `-config`. |
20+| `-acp` | bool | `false` | Serve the Agent Client Protocol on stdin/stdout instead of the terminal REPL. Also written `--acp`, or `acp` as the first argument (`mm acp agent.yaml`). |
21+| `-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. Also written `--tui`, or `tui` as the first argument (`mm tui agent.yaml`). |
2022 | `-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. |
2123 | `--version` | bool | `false` | Print the version and exit, before the configuration is read. `-version` is the same flag. |
2224 | `--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. |
@@ -9,14 +9,16 @@ mm [-config <path>] [-acp] [-tui] [-prompt <text>|-p <text>] [--version] [--abou
9 mm [-config <path>] --ask <agent> [-p <question>] (question on stdin when -p is absent)9 mm [-config <path>] --ask <agent> [-p <question>] (question on stdin when -p is absent)
10 mm [-config <path>] --ask-with-context <agent> [-p <question>] (context on stdin)10 mm [-config <path>] --ask-with-context <agent> [-p <question>] (context on stdin)
11 mm init [flags] (write a new agent.yaml; also mm --init)11 mm init [flags] (write a new agent.yaml; also mm --init)
12+mm tui [<path>] [flags] (same as mm -tui)
13+mm acp [<path>] [flags] (same as mm -acp)
12 ```14 ```
13 15
14 | Element | Type | Default | Description |16 | Element | Type | Default | Description |
15 |---------|------|---------|-------------|17 |---------|------|---------|-------------|
16 | `-config <path>` | string | `""` | Path of the YAML configuration file. |18 | `-config <path>` | string | `""` | Path of the YAML configuration file. |
17-| `<path>` | positional | none | Same as `-config`, when `-config` is not given. A second positional argument is an error. |19+| `<path>` | positional | none | Same as `-config`, when `-config` is not given. A second positional argument is an error. A first argument `init`, `tui` or `acp` is a mode word, not a path: a configuration file with one of these names is given as `./tui` or with `-config`. |
18-| `-acp` | bool | `false` | Serve the Agent Client Protocol on stdin/stdout instead of the terminal REPL. |20+| `-acp` | bool | `false` | Serve the Agent Client Protocol on stdin/stdout instead of the terminal REPL. Also written `--acp`, or `acp` as the first argument (`mm acp agent.yaml`). |
19-| `-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. |21+| `-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. Also written `--tui`, or `tui` as the first argument (`mm tui agent.yaml`). |
20 | `-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. |22 | `-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. |
21 | `--version` | bool | `false` | Print the version and exit, before the configuration is read. `-version` is the same flag. |23 | `--version` | bool | `false` | Print the version and exit, before the configuration is read. `-version` is the same flag. |
22 | `--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. |24 | `--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. |
modified docs/fr/reference/cli.md +5 -3
@@ -9,14 +9,16 @@ mm [-config <chemin>] [-acp] [-tui] [-prompt <texte>|-p <texte>] [--version] [--
99 mm [-config <chemin>] --ask <agent> [-p <question>] (question sur stdin sans -p)
1010 mm [-config <chemin>] --ask-with-context <agent> [-p <question>] (contexte sur stdin)
1111 mm init [options] (écrire un nouvel agent.yaml ; aussi mm --init)
12+mm tui [<chemin>] [options] (identique à mm -tui)
13+mm acp [<chemin>] [options] (identique à mm -acp)
1214 ```
1315
1416 | Élément | Type | Défaut | Description |
1517 |---------|------|--------|-------------|
1618 | `-config <chemin>` | chaîne | `""` | Chemin du fichier de configuration YAML. |
17-| `<chemin>` | positionnel | aucun | Équivalent de `-config` quand `-config` n'est pas donné. Un second argument positionnel est une erreur. |
18-| `-acp` | booléen | `false` | Sert l'Agent Client Protocol sur stdin/stdout au lieu du REPL du terminal. |
19-| `-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. |
19+| `<chemin>` | positionnel | aucun | Équivalent de `-config` quand `-config` n'est pas donné. Un second argument positionnel est une erreur. Un premier argument `init`, `tui` ou `acp` est un mot de mode, pas un chemin : un fichier de configuration portant l'un de ces noms se donne en `./tui` ou avec `-config`. |
20+| `-acp` | booléen | `false` | Sert l'Agent Client Protocol sur stdin/stdout au lieu du REPL du terminal. S'écrit aussi `--acp`, ou `acp` en premier argument (`mm acp agent.yaml`). |
21+| `-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. S'écrit aussi `--tui`, ou `tui` en premier argument (`mm tui agent.yaml`). |
2022 | `-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. |
2123 | `--version` | bool | `false` | Affiche la version et quitte, avant la lecture de la configuration. `-version` est la même option. |
2224 | `--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. |
@@ -9,14 +9,16 @@ mm [-config <chemin>] [-acp] [-tui] [-prompt <texte>|-p <texte>] [--version] [--
9 mm [-config <chemin>] --ask <agent> [-p <question>] (question sur stdin sans -p)9 mm [-config <chemin>] --ask <agent> [-p <question>] (question sur stdin sans -p)
10 mm [-config <chemin>] --ask-with-context <agent> [-p <question>] (contexte sur stdin)10 mm [-config <chemin>] --ask-with-context <agent> [-p <question>] (contexte sur stdin)
11 mm init [options] (écrire un nouvel agent.yaml ; aussi mm --init)11 mm init [options] (écrire un nouvel agent.yaml ; aussi mm --init)
12+mm tui [<chemin>] [options] (identique à mm -tui)
13+mm acp [<chemin>] [options] (identique à mm -acp)
12 ```14 ```
13 15
14 | Élément | Type | Défaut | Description |16 | Élément | Type | Défaut | Description |
15 |---------|------|--------|-------------|17 |---------|------|--------|-------------|
16 | `-config <chemin>` | chaîne | `""` | Chemin du fichier de configuration YAML. |18 | `-config <chemin>` | chaîne | `""` | Chemin du fichier de configuration YAML. |
17-| `<chemin>` | positionnel | aucun | Équivalent de `-config` quand `-config` n'est pas donné. Un second argument positionnel est une erreur. |19+| `<chemin>` | positionnel | aucun | Équivalent de `-config` quand `-config` n'est pas donné. Un second argument positionnel est une erreur. Un premier argument `init`, `tui` ou `acp` est un mot de mode, pas un chemin : un fichier de configuration portant l'un de ces noms se donne en `./tui` ou avec `-config`. |
18-| `-acp` | booléen | `false` | Sert l'Agent Client Protocol sur stdin/stdout au lieu du REPL du terminal. |20+| `-acp` | booléen | `false` | Sert l'Agent Client Protocol sur stdin/stdout au lieu du REPL du terminal. S'écrit aussi `--acp`, ou `acp` en premier argument (`mm acp agent.yaml`). |
19-| `-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. |21+| `-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. S'écrit aussi `--tui`, ou `tui` en premier argument (`mm tui agent.yaml`). |
20 | `-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. |22 | `-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. |
21 | `--version` | bool | `false` | Affiche la version et quitte, avant la lecture de la configuration. `-version` est la même option. |23 | `--version` | bool | `false` | Affiche la version et quitte, avant la lecture de la configuration. `-version` est la même option. |
22 | `--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. |24 | `--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. |
modified init_assemble_test.go +18 -0
@@ -4,6 +4,7 @@ import (
44 "context"
55 "os"
66 "path/filepath"
7+ "slices"
78 "testing"
89
910 "mm/internal/agentinit"
@@ -23,6 +24,23 @@ func TestIsInit(t *testing.T) {
2324 }
2425 }
2526
27+// `mm tui …` and `mm acp …` become their flags; a mode word anywhere else,
28+// or a path, is left alone.
29+func TestModeWordAsFlag(t *testing.T) {
30+ for _, c := range []struct{ in, want []string }{
31+ {[]string{"mm", "tui"}, []string{"mm", "-tui"}},
32+ {[]string{"mm", "acp", "agent.yaml"}, []string{"mm", "-acp", "agent.yaml"}},
33+ {[]string{"mm", "tui", "-config", "a.yaml"}, []string{"mm", "-tui", "-config", "a.yaml"}},
34+ {[]string{"mm", "agent.yaml", "tui"}, []string{"mm", "agent.yaml", "tui"}},
35+ {[]string{"mm", "./tui"}, []string{"mm", "./tui"}},
36+ {[]string{"mm"}, []string{"mm"}},
37+ } {
38+ if got := modeWordAsFlag(c.in); !slices.Equal(got, c.want) {
39+ t.Errorf("modeWordAsFlag(%q) = %q, want %q", c.in, got, c.want)
40+ }
41+ }
42+}
43+
2644 // A JSON agent written by `mm init` starts: structuredOutput forbids every
2745 // tool, and the generated file turns them all off — main is where that rule
2846 // is checked (config.StructuredOutputConflict), not config.Load.
@@ -4,6 +4,7 @@ import (
4 "context"4 "context"
5 "os"5 "os"
6 "path/filepath"6 "path/filepath"
7+ "slices"
7 "testing"8 "testing"
8 9
9 "mm/internal/agentinit"10 "mm/internal/agentinit"
@@ -23,6 +24,23 @@ func TestIsInit(t *testing.T) {
23 }24 }
24 }25 }
25 26
27+// `mm tui …` and `mm acp …` become their flags; a mode word anywhere else,
28+// or a path, is left alone.
29+func TestModeWordAsFlag(t *testing.T) {
30+ for _, c := range []struct{ in, want []string }{
31+ {[]string{"mm", "tui"}, []string{"mm", "-tui"}},
32+ {[]string{"mm", "acp", "agent.yaml"}, []string{"mm", "-acp", "agent.yaml"}},
33+ {[]string{"mm", "tui", "-config", "a.yaml"}, []string{"mm", "-tui", "-config", "a.yaml"}},
34+ {[]string{"mm", "agent.yaml", "tui"}, []string{"mm", "agent.yaml", "tui"}},
35+ {[]string{"mm", "./tui"}, []string{"mm", "./tui"}},
36+ {[]string{"mm"}, []string{"mm"}},
37+ } {
38+ if got := modeWordAsFlag(c.in); !slices.Equal(got, c.want) {
39+ t.Errorf("modeWordAsFlag(%q) = %q, want %q", c.in, got, c.want)
40+ }
41+ }
42+}
43+
26 // A JSON agent written by `mm init` starts: structuredOutput forbids every44 // A JSON agent written by `mm init` starts: structuredOutput forbids every
27 // tool, and the generated file turns them all off — main is where that rule45 // tool, and the generated file turns them all off — main is where that rule
28 // is checked (config.StructuredOutputConflict), not config.Load.46 // is checked (config.StructuredOutputConflict), not config.Load.
modified main.go +19 -2
@@ -80,6 +80,9 @@ func main() {
8080 if len(os.Args) > 1 && isInit(os.Args[1]) {
8181 os.Exit(agentinit.Main(os.Args[2:], os.Stdin, os.Stdout, agentinit.Options{Window: tui.RunInit, Terminal: tui.Terminal}))
8282 }
83+ // `mm tui` and `mm acp` (ticket 117): the modes as words too, like
84+ // `mm init` — `mm tui agent.yaml` is `mm -tui agent.yaml`.
85+ os.Args = modeWordAsFlag(os.Args)
8386
8487 // Handle --prompt/-p flag which can appear after the config file argument
8588 // We manually extract it before flag.Parse() so both orders work:
@@ -112,8 +115,8 @@ func main() {
112115 os.Args = append([]string{os.Args[0]}, remainingArgs...)
113116
114117 configPath := flag.String("config", "", "path to the YAML config file (default: $AGENT_CONFIG, then ./agent.yaml)")
115- acpMode := flag.Bool("acp", false, "serve the Agent Client Protocol on stdio (for Zed, JetBrains, Neovim…) instead of the terminal REPL")
116- 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")
118+ acpMode := flag.Bool("acp", false, "serve the Agent Client Protocol on stdio (for Zed, JetBrains, Neovim…) instead of the terminal REPL (same as: mm acp)")
119+ 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 (same as: mm tui)")
117120 promptMode := flag.String("prompt", "", "run a single prompt and exit")
118121 flag.StringVar(promptMode, "p", "", "shorthand for --prompt")
119122 showVersion := flag.Bool("version", false, "print the version and exit")
@@ -824,3 +827,17 @@ func runAsk(ctx context.Context, name string, withContext bool, prompt string) i
824827 func isInit(arg string) bool {
825828 return arg == "init" || arg == "--init" || arg == "-init"
826829 }
830+
831+// modeWordAsFlag turns a first argument `tui` or `acp` into its flag, so the
832+// rest of main sees one spelling:
833+//
834+// modeWordAsFlag([]string{"mm", "tui", "agent.yaml"}) // → mm -tui agent.yaml
835+//
836+// Only the first argument is a mode word: `mm agent.yaml tui` still names two
837+// config files, and a config file called tui is reached as ./tui.
838+func modeWordAsFlag(args []string) []string {
839+ if len(args) < 2 || (args[1] != "tui" && args[1] != "acp") {
840+ return args
841+ }
842+ return append([]string{args[0], "-" + args[1]}, args[2:]...)
843+}
@@ -80,6 +80,9 @@ func main() {
80 if len(os.Args) > 1 && isInit(os.Args[1]) {80 if len(os.Args) > 1 && isInit(os.Args[1]) {
81 os.Exit(agentinit.Main(os.Args[2:], os.Stdin, os.Stdout, agentinit.Options{Window: tui.RunInit, Terminal: tui.Terminal}))81 os.Exit(agentinit.Main(os.Args[2:], os.Stdin, os.Stdout, agentinit.Options{Window: tui.RunInit, Terminal: tui.Terminal}))
82 }82 }
83+ // `mm tui` and `mm acp` (ticket 117): the modes as words too, like
84+ // `mm init` — `mm tui agent.yaml` is `mm -tui agent.yaml`.
85+ os.Args = modeWordAsFlag(os.Args)
83 86
84 // Handle --prompt/-p flag which can appear after the config file argument87 // Handle --prompt/-p flag which can appear after the config file argument
85 // We manually extract it before flag.Parse() so both orders work:88 // We manually extract it before flag.Parse() so both orders work:
@@ -112,8 +115,8 @@ func main() {
112 os.Args = append([]string{os.Args[0]}, remainingArgs...)115 os.Args = append([]string{os.Args[0]}, remainingArgs...)
113 116
114 configPath := flag.String("config", "", "path to the YAML config file (default: $AGENT_CONFIG, then ./agent.yaml)")117 configPath := flag.String("config", "", "path to the YAML config file (default: $AGENT_CONFIG, then ./agent.yaml)")
115- acpMode := flag.Bool("acp", false, "serve the Agent Client Protocol on stdio (for Zed, JetBrains, Neovim…) instead of the terminal REPL")118+ acpMode := flag.Bool("acp", false, "serve the Agent Client Protocol on stdio (for Zed, JetBrains, Neovim…) instead of the terminal REPL (same as: mm acp)")
116- 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")119+ 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 (same as: mm tui)")
117 promptMode := flag.String("prompt", "", "run a single prompt and exit")120 promptMode := flag.String("prompt", "", "run a single prompt and exit")
118 flag.StringVar(promptMode, "p", "", "shorthand for --prompt")121 flag.StringVar(promptMode, "p", "", "shorthand for --prompt")
119 showVersion := flag.Bool("version", false, "print the version and exit")122 showVersion := flag.Bool("version", false, "print the version and exit")
@@ -824,3 +827,17 @@ func runAsk(ctx context.Context, name string, withContext bool, prompt string) i
824 func isInit(arg string) bool {827 func isInit(arg string) bool {
825 return arg == "init" || arg == "--init" || arg == "-init"828 return arg == "init" || arg == "--init" || arg == "-init"
826 }829 }
830+
831+// modeWordAsFlag turns a first argument `tui` or `acp` into its flag, so the
832+// rest of main sees one spelling:
833+//
834+// modeWordAsFlag([]string{"mm", "tui", "agent.yaml"}) // → mm -tui agent.yaml
835+//
836+// Only the first argument is a mode word: `mm agent.yaml tui` still names two
837+// config files, and a config file called tui is reached as ./tui.
838+func modeWordAsFlag(args []string) []string {
839+ if len(args) < 2 || (args[1] != "tui" && args[1] != "acp") {
840+ return args
841+ }
842+ return append([]string{args[0], "-" + args[1]}, args[2:]...)
843+}