diff --git a/crates/minimal/src/lib.rs b/crates/minimal/src/lib.rs index 20e660347..ad0910c0d 100644 --- a/crates/minimal/src/lib.rs +++ b/crates/minimal/src/lib.rs @@ -45,9 +45,9 @@ pub enum Command { /// List sessions // // Deliberate exception to the ` ` convention (documented in - // docs/reference/cli.md): `min ls` is the highest-traffic command in the - // CLI and keeps its bare top-level form. Not an oversight — do not move it - // under `session`. + // docs/reference/cli.md): `min session list` is the canonical spelling, + // and `min ls` — the highest-traffic command in the CLI — keeps this bare + // top-level form as its visible alias. Not an oversight — do not remove it. Ls(LsArgs), /// Shut down the minimald daemon // @@ -163,6 +163,9 @@ pub struct SessionArgs { #[derive(Debug, Subcommand)] pub enum SessionCommand { + /// List sessions + #[command(visible_alias = "ls")] + List(LsArgs), /// Activate (create) a new session Activate(ActivateArgs), /// Attach to an existing session @@ -649,6 +652,7 @@ async fn run_command(cli: Cli) -> Result<(), anyhow::Error> { Some(Command::Ls(args)) => cmd_ls(&cli.global_args, args).await, Some(Command::Stop(args)) => cmd_stop(&cli.global_args, args).await, Some(Command::Session(SessionArgs { command })) => match command { + SessionCommand::List(args) => cmd_ls(&cli.global_args, args).await, SessionCommand::Activate(args) => cmd_activate(&cli.global_args, args).await, SessionCommand::Attach(args) => cmd_attach(&cli.global_args, args).await, SessionCommand::Destroy(args) => cmd_destroy(&cli.global_args, args).await, @@ -2833,6 +2837,42 @@ mod tests { assert!(!cli.global_args.use_minvmd()); } + /// `min session list` is the canonical ` list` spelling of the + /// flagship list command; `min ls` (top-level) and `min session ls` + /// (noun-level) are visible aliases. All three parse to the same `LsArgs`, + /// so `--raw`/`--json` reach the one `cmd_ls` implementation identically. + #[test] + fn session_list_spellings_all_reach_ls() { + use clap::Parser as _; + let ls_args = |args: &[&str]| -> LsArgs { + match Cli::try_parse_from(args).unwrap().command { + Some(Command::Ls(a)) + | Some(Command::Session(SessionArgs { + command: SessionCommand::List(a), + })) => a, + _ => panic!("expected an ls command for {args:?}"), + } + }; + + for spelling in [ + ["min", "session", "list"].as_slice(), + ["min", "session", "ls"].as_slice(), + ["min", "ls"].as_slice(), + ] { + let a = ls_args(spelling); + assert!( + !a.raw && !a.json, + "{spelling:?} must default both flags off" + ); + } + + // `--raw`/`--json` are accepted on the canonical and the bare form alike. + let canonical = ls_args(&["min", "session", "list", "--raw", "--json"]); + assert!(canonical.raw && canonical.json); + let bare = ls_args(&["min", "ls", "--json"]); + assert!(bare.json && !bare.raw); + } + /// `repo_dir` and `minimal_dir` are global, so they must be accepted after /// the subcommand — not just before it (#1039). #[test] diff --git a/docs/reference/cli-min.md b/docs/reference/cli-min.md index 6549d2162..1ed6fc66b 100644 --- a/docs/reference/cli-min.md +++ b/docs/reference/cli-min.md @@ -37,10 +37,10 @@ These apply to every subcommand. ## Commands -### `ls` +### `session list` (aliases: `min ls`, `min session ls`) ``` -min ls [--raw] [--json] +min session list [--raw] [--json] ``` Lists sessions. `--raw` prints raw session IDs one per line for piping @@ -49,8 +49,10 @@ JSON. When the daemon reports a shared resource pool, the table is headed by a `RESOURCE POOL:` line (CPU cores, memory, and the number of sessions sharing them); `--raw` omits it. -A deliberate exception to the `min ` convention: `ls` is the -highest-traffic command in the CLI and keeps its bare top-level form. +`min ls` is the same command kept bare at the top level — a deliberate +exception to the `min ` convention, since it is the +highest-traffic command in the CLI; `min session ls` is the noun-level alias. +All three spellings take the same flags and produce identical output. ### `session activate` diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 6391b901a..1662b1008 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -54,7 +54,7 @@ ergonomic choices, not leftovers — do not "fix" them: | Form | Why it stays | |------|--------------| -| `min ls` | The highest-traffic command in the CLI; the break is not worth the consistency. | +| `min ls` | Visible top-level alias of the canonical `min session list`; the highest-traffic command keeps its bare form. | | `min stop` | Acts on the daemon backend rather than any session, and is the daemon-lifecycle command people reach for. | | `min init`, `min add`, `min update` | Passthroughs to the `mip` commands of the same name; keeping the spelling identical across the two CLIs beats the hierarchy. |