diff --git a/cli/cli.go b/cli/cli.go index dffd08b0..8b911ec4 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -48,6 +48,11 @@ func Run(args []string) int { return 1 } + if shouldShowTopLevelHelp(execArgs) { + commands.RenderTopLevelHelp(d) + return 0 + } + err = d.Execute(execArgs) if err != nil { if errors.Is(err, context.Canceled) { @@ -66,6 +71,22 @@ func Run(args []string) int { return 0 } +// shouldShowTopLevelHelp returns true when the args indicate we should render +// top-level help (no args, or just -h/--help with no command). +func shouldShowTopLevelHelp(args []string) bool { + if len(args) == 0 { + return true + } + // Only help flags, no command words + for _, arg := range args { + if arg == "-h" || arg == "--help" { + continue + } + return false + } + return true +} + // printError renders an error to stderr. If the error implements // ui.TerminalError, it gets colorized multi-line output; otherwise // it falls back to a plain "ERROR: ..." line. diff --git a/cli/commands/commands.go b/cli/commands/commands.go index 965b50bd..fb54c70b 100644 --- a/cli/commands/commands.go +++ b/cli/commands/commands.go @@ -8,6 +8,7 @@ import ( func RegisterAll(d *mflags.Dispatcher) { // Core commands d.Dispatch("version", Infer("version", "Print the version", Version, + WithGroup(GroupClient), WithExample(mflags.Example{ Name: "Print version", Body: "miren version", @@ -18,6 +19,7 @@ func RegisterAll(d *mflags.Dispatcher) { }), )) d.Dispatch("login", Infer("login", "Authenticate with miren.cloud", Login, + WithGroup(GroupClient), WithExample(mflags.Example{ Name: "Login", Body: "miren login", @@ -28,12 +30,14 @@ func RegisterAll(d *mflags.Dispatcher) { }), )) d.Dispatch("logout", Infer("logout", "Remove local authentication credentials", Logout, + WithGroup(GroupClient), WithExample(mflags.Example{ Name: "Logout", Body: "miren logout", }), )) d.Dispatch("whoami", Infer("whoami", "Display information about the current authenticated user", Whoami, + WithGroup(GroupClient), WithExample(mflags.Example{ Name: "Show current user", Body: "miren whoami", @@ -46,6 +50,7 @@ func RegisterAll(d *mflags.Dispatcher) { // Doctor commands d.Dispatch("doctor", Infer("doctor", "Diagnose miren environment and connectivity", Doctor, + WithGroup(GroupClient), WithExample(mflags.Example{ Name: "Run all diagnostics", Body: "miren doctor", @@ -72,6 +77,7 @@ func RegisterAll(d *mflags.Dispatcher) { // App lifecycle commands d.Dispatch("init", Infer("init", "Initialize a new application", Init, + WithGroup(GroupGettingStarted), WithExample(mflags.Example{ Name: "Initialize in current directory", Body: "miren init", @@ -82,6 +88,7 @@ func RegisterAll(d *mflags.Dispatcher) { }), )) d.Dispatch("deploy", Infer("deploy", "Deploy an application", Deploy, + WithGroup(GroupGettingStarted), WithExample(mflags.Example{ Name: "Basic", Body: "miren deploy", @@ -114,6 +121,7 @@ miren deploy --analyze }), )) d.Dispatch("rollback", Infer("rollback", "Roll back to a previous version", Rollback, + WithGroup(GroupGettingStarted), WithExample(mflags.Example{ Name: "Rollback the app in the current directory", Body: "miren rollback", @@ -124,6 +132,7 @@ miren deploy --analyze }), )) d.Dispatch("logs", Infer("logs", "View logs (defaults to app logs)", LogsApp, + WithGroup(GroupMonitoring), WithDescription(logsDescription), WithExample(mflags.Example{ Name: "View logs for the current app", @@ -190,6 +199,7 @@ miren deploy --analyze // App management commands d.Dispatch("app", Infer("app", "Get information about an application", App, + WithGroup(GroupMonitoring), WithExample(mflags.Example{ Name: "Show app info for the current directory", Body: "miren app", @@ -287,6 +297,7 @@ miren deploy --analyze }), )) d.Dispatch("apps", Infer("apps", "List all applications (alias for 'app list')", AppList, + WithGroup(GroupMonitoring), WithExample(mflags.Example{ Name: "List all apps", Body: "miren apps", @@ -294,7 +305,7 @@ miren deploy --analyze )) // Sandbox commands - d.Dispatch("sandbox", Section("sandbox", "Sandbox management commands", "", WithSectionDescription(sandboxSectionDescription))) + d.Dispatch("sandbox", Section("sandbox", "Sandbox management commands", "", WithSectionDescription(sandboxSectionDescription), WithSectionGroup(GroupMonitoring))) d.Dispatch("sandbox list", Infer("sandbox list", "List sandboxes (excludes dead by default)", SandboxList, WithExample(mflags.Example{ Name: "List running sandboxes", @@ -338,7 +349,7 @@ miren deploy --analyze )) // Sandbox pool commands - d.Dispatch("sandbox-pool", Section("sandbox-pool", "Sandbox pool management commands", "")) + d.Dispatch("sandbox-pool", Section("sandbox-pool", "Sandbox pool management commands", "", WithSectionGroup(GroupMonitoring))) d.Dispatch("sandbox-pool list", Infer("sandbox-pool list", "List all sandbox pools", SandboxPoolList, WithExample(mflags.Example{ Name: "List all pools", @@ -353,7 +364,7 @@ miren deploy --analyze )) // Environment variable commands - d.Dispatch("env", Section("env", "Environment variable management commands", "")) + d.Dispatch("env", Section("env", "Environment variable management commands", "", WithSectionGroup(GroupConfiguring))) d.Dispatch("env set", Infer("env set", "Set environment variables for an application", EnvSet, WithExample(mflags.Example{ Name: "Set an environment variable", @@ -409,7 +420,7 @@ miren deploy --analyze // Addon commands (gated behind labs flag) if labs.Addons() { - d.Dispatch("addon", Section("addon", "Addon management commands", "")) + d.Dispatch("addon", Section("addon", "Addon management commands", "", WithSectionGroup(GroupConfiguring))) d.Dispatch("addon list-available", Infer("addon list-available", "List available addons", AddonListAvailable, WithLabsFeature(labs.FeatureAddons), WithExample(mflags.Example{ @@ -457,6 +468,7 @@ miren deploy --analyze // Route commands d.Dispatch("route", Infer("route", "List all HTTP routes", Route, + WithGroup(GroupConfiguring), WithExample(mflags.Example{ Name: "List all routes", Body: "miren route", @@ -544,7 +556,7 @@ miren deploy --analyze } // Config commands - d.Dispatch("config", Section("config", "Configuration file management", "")) + d.Dispatch("config", Section("config", "Configuration file management", "", WithSectionGroup(GroupClient))) d.Dispatch("config info", Infer("config info", "Show configuration file locations and format", ConfigInfo, WithExample(mflags.Example{ Name: "Show config info", @@ -564,6 +576,7 @@ miren deploy --analyze // Cluster commands d.Dispatch("cluster", Infer("cluster", "List configured clusters", Cluster, + WithGroup(GroupClient), WithExample(mflags.Example{ Name: "List clusters", Body: "miren cluster", @@ -622,7 +635,7 @@ miren deploy --analyze // Runner commands (distributed runners) - behind feature flag if labs.DistributedRunners() { - d.Dispatch("runner", Section("runner", "Runner management commands", "")) + d.Dispatch("runner", Section("runner", "Runner management commands", "", WithSectionGroup(GroupServer))) d.Dispatch("runner token", Section("runner token", "Manage join tokens", "")) d.Dispatch("runner token create", Infer("runner token create", "Create a join token for a runner", RunnerTokenCreate, WithLabsFeature(labs.FeatureDistributedRunners), @@ -755,6 +768,7 @@ miren deploy --analyze // Server commands d.Dispatch("server", Infer("server", "Start the miren server", Server, + WithGroup(GroupServer), WithExample(mflags.Example{ Name: "Start in standalone mode", Body: "miren server --mode standalone", @@ -834,7 +848,7 @@ miren deploy --analyze )) // CLI management commands - d.Dispatch("download", Section("download", "Download management commands", "")) + d.Dispatch("download", Section("download", "Download management commands", "", WithSectionGroup(GroupServer))) d.Dispatch("download release", Infer("download release", "Download and extract miren release", DownloadRelease, WithExample(mflags.Example{ Name: "Download the latest release", @@ -842,6 +856,7 @@ miren deploy --analyze }), )) d.Dispatch("upgrade", Infer("upgrade", "Upgrade miren CLI to latest version", Upgrade, + WithGroup(GroupClient), WithExample(mflags.Example{ Name: "Upgrade to latest", Body: "miren upgrade", @@ -857,7 +872,7 @@ miren deploy --analyze )) // Auth commands - d.Dispatch("auth", Section("auth", "Authentication commands", "")) + d.Dispatch("auth", Section("auth", "Authentication commands", "", WithSectionGroup(GroupConfiguring))) d.Dispatch("auth generate", Infer("auth generate", "Generate authentication config file", AuthGenerate, WithExample(mflags.Example{ Name: "Generate auth config", @@ -895,6 +910,7 @@ miren deploy --analyze // Admin commands d.Dispatch("admin", Infer("admin", "Call an admin method on an application", Admin, + WithGroup(GroupConfiguring), WithDescription(adminDescription), WithExample(mflags.Example{ Name: "List available admin methods", @@ -920,7 +936,7 @@ Use these commands to help diagnose issues with the miren runtime. Warning: These commands are intended for advanced users and developers. They may change or be removed without notice. -`)) +`, WithSectionGroup(GroupServer))) d.Dispatch("debug connection", Infer("debug connection", "Test connectivity and authentication with a server", DebugConnection)) d.Dispatch("debug advertise", Infer("debug advertise", "Show which addresses the server would advertise and why", DebugAdvertise)) d.Dispatch("debug reindex", Infer("debug reindex", "Rebuild all entity indexes from scratch", DebugReindex)) @@ -949,6 +965,7 @@ Warning: These commands are intended for advanced users and developers. They may d.Dispatch("debug entity ensure", Infer("debug entity ensure", "Ensure an entity exists", EntityEnsure)) // Disk commands + d.Dispatch("disk", Section("disk", "Disk backup and recovery", "", WithSectionGroup(GroupServer))) d.Dispatch("disk backup", Infer("disk backup", "Backup a disk to a snapshot file", DiskBackup)) d.Dispatch("disk restore", Infer("disk restore", "Restore a disk from a snapshot file", DiskRestore)) d.Dispatch("disk undelete", Infer("disk undelete", "Restore a recently deleted disk", DiskUndelete)) @@ -980,21 +997,14 @@ Warning: These commands are intended for advanced users and developers. They may d.Dispatch("debug netdb gc", Infer("debug netdb gc", "Find and release orphaned IP leases", DebugNetDBGC)) // Internal commands (hidden from help, used by miren internals) - d.Dispatch("internal", Section("internal", "Internal commands used by miren components", "")) + d.Dispatch("internal", Section("internal", "Internal commands used by miren components", "", WithSectionGroup(GroupHidden))) // Alias commands + d.Dispatch("alias", Section("alias", "CLI alias management", "", WithSectionGroup(GroupClient))) d.Dispatch("alias list", Infer("alias list", "List configured CLI aliases", AliasList)) // Help command (registered last so it can reference all other commands) d.Dispatch("help", NewHelpCommand(d)) - d.Dispatch("help alias", Infer("help alias", "Learn how to define and use CLI aliases", HelpAlias)) addCommands(d) } - -func HiddenCommands() []string { - return []string{ - "internal", - "debug", - } -} diff --git a/cli/commands/help.go b/cli/commands/help.go index dc67e3ee..0477d229 100644 --- a/cli/commands/help.go +++ b/cli/commands/help.go @@ -11,6 +11,7 @@ type section struct { help string desc string description string + group string fs *mflags.FlagSet } @@ -25,6 +26,13 @@ func WithSectionDescription(desc string) SectionOption { } } +// WithSectionGroup assigns this section to a named group for help rendering. +func WithSectionGroup(group string) SectionOption { + return func(s *section) { + s.group = group + } +} + func Section(name, desc, help string, opts ...SectionOption) mflags.Command { help = strings.TrimSpace(help) @@ -77,3 +85,8 @@ func (s *section) Synopsis() string { func (s *section) Description() string { return s.description } + +// CommandGroup implements mflags.CommandGroupProvider. +func (s *section) CommandGroup() string { + return s.group +} diff --git a/cli/commands/help_alias.go b/cli/commands/help_alias.go deleted file mode 100644 index 4c9ce6e0..00000000 --- a/cli/commands/help_alias.go +++ /dev/null @@ -1,88 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "sort" - "text/tabwriter" - - "miren.dev/runtime/appconfig" - "miren.dev/runtime/pkg/color" -) - -type helpAliasOpts struct{} - -func HelpAlias(ctx *Context, opts helpAliasOpts) error { - bold := color.New(color.Bold) - faint := color.New(color.Faint) - cyan := color.New(color.FgCyan) - green := color.New(color.FgGreen) - - bold.Println("CLI Aliases") - fmt.Println() - fmt.Println("Aliases let you define custom shortcuts for frequently-used commands.") - fmt.Printf("Define them in %s:\n", cyan.Sprint(appconfig.AppConfigPath)) - fmt.Println() - - faint.Println(" [aliases]") - faint.Println(` console = "app run bin/rails console"`) - faint.Println(` tail = "logs app -f"`) - fmt.Println() - - bold.Println("Usage") - fmt.Println() - fmt.Printf(" miren %s %s miren app run bin/rails console\n", - green.Sprint("console"), faint.Sprint("→")) - fmt.Printf(" miren %s -n 50 %s miren logs app -f -n 50\n", - green.Sprint("tail"), faint.Sprint("→")) - fmt.Println() - fmt.Println(" Extra arguments are appended to the expanded command.") - fmt.Println() - - bold.Println("Multi-word aliases") - fmt.Println() - fmt.Println(" Alias names can contain multiple words to create namespaces:") - fmt.Println() - faint.Println(` "x tail" = "logs app -f"`) - fmt.Println() - fmt.Printf(" miren %s %s miren logs app -f\n", - green.Sprint("x tail"), faint.Sprint("→")) - fmt.Println() - - bold.Println("Rules") - fmt.Println() - fmt.Println(" - Alias names must not shadow built-in commands.") - fmt.Println(" - Aliases expand once — an alias cannot reference another alias.") - fmt.Println(" - Names use lowercase letters, numbers, dashes, and underscores.") - fmt.Println() - - ac, err := appconfig.LoadAppConfig() - if err != nil { - printConfigWarning(err) - fmt.Println() - return nil - } - - if ac == nil || len(ac.Aliases) == 0 { - faint.Println("No aliases configured.") - fmt.Printf("Add an %s section to %s to get started.\n", - cyan.Sprint("[aliases]"), cyan.Sprint(appconfig.AppConfigPath)) - return nil - } - - bold.Println("Configured aliases") - fmt.Println() - - names := make([]string, 0, len(ac.Aliases)) - for name := range ac.Aliases { - names = append(names, name) - } - sort.Strings(names) - - w := tabwriter.NewWriter(os.Stdout, 0, 4, 2, ' ', 0) - for _, name := range names { - fmt.Fprintf(w, " %s\t%s %s\n", - green.Sprint(name), faint.Sprint("→"), ac.Aliases[name]) - } - return w.Flush() -} diff --git a/cli/commands/help_commands.go b/cli/commands/help_commands.go index 9594d5b0..6e4b8099 100644 --- a/cli/commands/help_commands.go +++ b/cli/commands/help_commands.go @@ -29,10 +29,18 @@ func NewHelpCommand(d *mflags.Dispatcher) *Cmd { return runListCommands(d, opts) } if len(opts.Commands) > 0 { + // If the joined args form a real command path, treat them as one. + // This makes `miren help debug entity list` work the same as + // `miren help debug.entity.list`. + if len(opts.Commands) > 1 && d.HasCommand(strings.Join(opts.Commands, " ")) { + opts.Commands = []string{strings.Join(opts.Commands, " ")} + } return runMultiHelp(d, opts) } - return mflags.ErrShowHelp + RenderTopLevelHelp(d) + return nil }, + WithGroup(GroupClient), WithExample(mflags.Example{ Name: "List all commands", Body: "miren help --commands", diff --git a/cli/commands/help_groups.go b/cli/commands/help_groups.go new file mode 100644 index 00000000..dc478f93 --- /dev/null +++ b/cli/commands/help_groups.go @@ -0,0 +1,27 @@ +package commands + +// Help group constants — used both as the CommandGroup value on registered +// commands and as the display label in help output. +// +// Every top-level command should be tagged with one of these groups. The +// TestAllTopLevelCommandsHaveKnownGroup test catches drift. +const ( + GroupGettingStarted = "Getting started" + GroupMonitoring = "Monitoring your app" + GroupConfiguring = "Configuring your app" + GroupClient = "Client operations" + GroupServer = "Server operations" + + // GroupHidden commands are registered but filtered from help output. + GroupHidden = "Hidden" +) + +// HelpGroupOrder controls the order groups are rendered in top-level help. +// GroupHidden is intentionally absent — commands in that group are filtered. +var HelpGroupOrder = []string{ + GroupGettingStarted, + GroupMonitoring, + GroupConfiguring, + GroupClient, + GroupServer, +} diff --git a/cli/commands/help_groups_test.go b/cli/commands/help_groups_test.go new file mode 100644 index 00000000..80bdb933 --- /dev/null +++ b/cli/commands/help_groups_test.go @@ -0,0 +1,42 @@ +package commands + +import ( + "testing" + + "miren.dev/mflags" + "miren.dev/runtime/pkg/labs" +) + +// TestAllTopLevelCommandsHaveKnownGroup fails if any top-level command is +// missing a CommandGroup or has a CommandGroup not in HelpGroupOrder (or the +// Hidden group). This prevents: +// - Forgetting to tag a new command with WithGroup/WithSectionGroup. +// - Typo'd group strings that would silently create a phantom group. +// - Implicit namespaces at the top level, which cannot carry group metadata +// and should be made explicit with a Section registration. +func TestAllTopLevelCommandsHaveKnownGroup(t *testing.T) { + labs.EnableAll() + + d := mflags.NewDispatcher("miren") + RegisterAll(d) + + known := make(map[string]bool) + for _, g := range HelpGroupOrder { + known[g] = true + } + known[GroupHidden] = true + + for _, child := range d.GetDirectChildren("") { + if !child.IsEntry { + t.Errorf("%q is an implicit namespace — register a parent Section so it can be grouped", child.Name) + continue + } + if child.Group == "" { + t.Errorf("%q has no CommandGroup — tag it with WithGroup/WithSectionGroup", child.Name) + continue + } + if !known[child.Group] { + t.Errorf("%q has group %q which is not in HelpGroupOrder (or GroupHidden)", child.Name, child.Group) + } + } +} diff --git a/cli/commands/help_render.go b/cli/commands/help_render.go new file mode 100644 index 00000000..d1da27e0 --- /dev/null +++ b/cli/commands/help_render.go @@ -0,0 +1,79 @@ +package commands + +import ( + "fmt" + + "github.com/charmbracelet/lipgloss" + "miren.dev/mflags" +) + +// RenderTopLevelHelp renders grouped help output for the top-level command list. +// Commands are rendered in the order defined by HelpGroupOrder. Commands in +// GroupHidden are filtered out. +func RenderTopLevelHelp(d *mflags.Dispatcher) { + children := d.GetDirectChildren("") + + grouped := make(map[string][]mflags.ChildEntry) + for _, child := range children { + if child.Group == GroupHidden { + continue + } + grouped[child.Group] = append(grouped[child.Group], child) + } + + // Compute max name length across rendered commands for column alignment. + maxLen := 0 + for _, group := range HelpGroupOrder { + for _, child := range grouped[group] { + if len(child.Name) > maxLen { + maxLen = len(child.Name) + } + } + } + + headerStyle := lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("220")) + + fmt.Printf("Usage: %s [arguments]\n", d.Name()) + + for _, group := range HelpGroupOrder { + entries := grouped[group] + if len(entries) == 0 { + continue + } + fmt.Println() + fmt.Println(headerStyle.Render(fmt.Sprintf("%s:", group))) + for _, child := range entries { + fmt.Println(formatHelpLine(d, child, maxLen)) + } + } + + fmt.Println() + fmt.Printf("Use '%s help ' or '%s --help' for more information.\n", d.Name(), d.Name()) +} + +// formatHelpLine formats a single command entry for the help listing. +func formatHelpLine(d *mflags.Dispatcher, child mflags.ChildEntry, maxLen int) string { + grandchildren := d.GetDirectChildren(child.Path) + + faint := lipgloss.NewStyle().Faint(true) + + suffix := "" + if len(grandchildren) > 0 { + suffix = " " + faint.Render(subCommandsLabel(len(grandchildren))) + } + + if child.Usage != "" { + return fmt.Sprintf(" %-*s %s%s", maxLen+2, child.Name, child.Usage, suffix) + } + if suffix != "" { + return fmt.Sprintf(" %-*s %s", maxLen+2, child.Name, suffix) + } + return fmt.Sprintf(" %s", child.Name) +} + +func subCommandsLabel(n int) string { + if n == 1 { + return "(1 sub-command)" + } + return fmt.Sprintf("(%d sub-commands)", n) +} diff --git a/cli/commands/infer.go b/cli/commands/infer.go index 14a2a47c..e0320f26 100644 --- a/cli/commands/infer.go +++ b/cli/commands/infer.go @@ -26,6 +26,7 @@ type Cmd struct { examples []mflags.Example labsFeature string description string + group string } type CommandOption func(*Cmd) @@ -50,6 +51,13 @@ func WithLabsFeature(feature string) CommandOption { } } +// WithGroup assigns this command to a named group for help rendering. +func WithGroup(group string) CommandOption { + return func(c *Cmd) { + c.group = group + } +} + // Infer creates a command from a function with the signature: // func(ctx *Context, opts StructType) error func Infer(name, syn string, f interface{}, opts ...CommandOption) *Cmd { @@ -127,6 +135,11 @@ func (w *Cmd) Description() string { return w.description } +// CommandGroup implements mflags.CommandGroupProvider. +func (w *Cmd) CommandGroup() string { + return w.group +} + // FlagSet implements mflags.Command func (w *Cmd) FlagSet() *mflags.FlagSet { return w.fs diff --git a/docs/command-sidebar.json b/docs/command-sidebar.json index c401e772..34c0c20a 100644 --- a/docs/command-sidebar.json +++ b/docs/command-sidebar.json @@ -214,18 +214,7 @@ "command/env-set" ] }, - { - "type": "category", - "label": "help", - "collapsed": true, - "link": { - "type": "doc", - "id": "command/help" - }, - "items": [ - "command/help-alias" - ] - }, + "command/help", "command/init", "command/login", "command/logout", diff --git a/docs/docs/command/alias.md b/docs/docs/command/alias.md index afb7e95d..6b9b7fab 100644 --- a/docs/docs/command/alias.md +++ b/docs/docs/command/alias.md @@ -1,12 +1,12 @@ --- title: "miren alias" sidebar_label: "alias" -description: "" +description: "CLI alias management" --- # miren alias - +CLI alias management ## Usage diff --git a/docs/docs/command/disk.md b/docs/docs/command/disk.md index f355db5f..f66c5d48 100644 --- a/docs/docs/command/disk.md +++ b/docs/docs/command/disk.md @@ -1,12 +1,12 @@ --- title: "miren disk" sidebar_label: "disk" -description: "" +description: "Disk backup and recovery" --- # miren disk - +Disk backup and recovery ## Usage diff --git a/docs/docs/command/help-alias.md b/docs/docs/command/help-alias.md deleted file mode 100644 index f88bba5e..00000000 --- a/docs/docs/command/help-alias.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: "miren help alias" -sidebar_label: "help alias" -description: "Learn how to define and use CLI aliases" ---- - -# miren help alias - -Learn how to define and use CLI aliases - -## Usage - -```bash -miren help alias [flags] -``` - -## Global Options - -- `--options` — Path to file containing options -- `--server-address` — Server address to connect to (default: `127.0.0.1:8443`) -- `--verbose, -v` — Enable verbose output - -## See also - -- [`miren help`](/command/help) diff --git a/docs/docs/command/help.md b/docs/docs/command/help.md index 65152742..3d3e7b87 100644 --- a/docs/docs/command/help.md +++ b/docs/docs/command/help.md @@ -45,7 +45,3 @@ miren help --commands --format json ```bash miren help app.list version sandbox.stop ``` - -## Subcommands - -- [`miren help alias`](/command/help-alias) — Learn how to define and use CLI aliases diff --git a/docs/docs/commands.md b/docs/docs/commands.md index 8ea1c176..4f778c9e 100644 --- a/docs/docs/commands.md +++ b/docs/docs/commands.md @@ -29,7 +29,7 @@ Complete reference for all `miren` CLI commands. | Command | Description | |---------|-------------| -| [`miren alias`](/command/alias) | | +| [`miren alias`](/command/alias) | CLI alias management | | [`miren alias list`](/command/alias-list) | List configured CLI aliases | ## app @@ -98,7 +98,7 @@ Complete reference for all `miren` CLI commands. | Command | Description | |---------|-------------| -| [`miren disk`](/command/disk) | | +| [`miren disk`](/command/disk) | Disk backup and recovery | | [`miren disk backup`](/command/disk-backup) | Backup a disk to a snapshot file | | [`miren disk list-deleted`](/command/disk-list-deleted) | List deleted disks available for recovery | | [`miren disk restore`](/command/disk-restore) | Restore a disk from a snapshot file | @@ -135,7 +135,6 @@ Complete reference for all `miren` CLI commands. | Command | Description | |---------|-------------| | [`miren help`](/command/help) | Show help for one or more commands | -| [`miren help alias`](/command/help-alias) | Learn how to define and use CLI aliases | ## init diff --git a/go.mod b/go.mod index 04bfe661..af690369 100644 --- a/go.mod +++ b/go.mod @@ -128,7 +128,7 @@ require ( k8s.io/klog/v2 v2.130.1 miren.dev/jsonrpc3/go/jsonrpc3 v0.0.0-20260106052505-c98e2702b093 miren.dev/lbd v0.0.0-20260224020427-8914d8db2233 - miren.dev/mflags v0.0.0-20260313175018-d9ee90a8bb13 + miren.dev/mflags v0.0.0-20260518222642-0ca7adc28461 sigs.k8s.io/knftables v0.0.21 ) diff --git a/go.sum b/go.sum index 01f63300..e85b44b6 100644 --- a/go.sum +++ b/go.sum @@ -1981,8 +1981,8 @@ miren.dev/jsonrpc3/go/jsonrpc3 v0.0.0-20260106052505-c98e2702b093 h1:Sd+M5HSUati miren.dev/jsonrpc3/go/jsonrpc3 v0.0.0-20260106052505-c98e2702b093/go.mod h1:B4A3wSzkcSZQw6Y5opU+rk1+1lEuCWIWkAiN7TkltGE= miren.dev/lbd v0.0.0-20260224020427-8914d8db2233 h1:9DxH7Dhnmu7hn1OA2JC5fHpLuVgAqBySws9GLNssLl4= miren.dev/lbd v0.0.0-20260224020427-8914d8db2233/go.mod h1:+x9fy2p45csBnGUJdqxCUmzlUTCipoVDbv6zIapTgDA= -miren.dev/mflags v0.0.0-20260313175018-d9ee90a8bb13 h1:QPWolXOmZOvh5CBG0i+7QWxBgTzT0nwDlRMHgMpo9P8= -miren.dev/mflags v0.0.0-20260313175018-d9ee90a8bb13/go.mod h1:G1eQ/upWVdO6BGT6dlh5Yqjt+9ncH5RUAKX6UKi1F9Q= +miren.dev/mflags v0.0.0-20260518222642-0ca7adc28461 h1:ETSN/0nBy1Dqpu43INesvPWoipOaC5+pfKzRjngkeO0= +miren.dev/mflags v0.0.0-20260518222642-0ca7adc28461/go.mod h1:G1eQ/upWVdO6BGT6dlh5Yqjt+9ncH5RUAKX6UKi1F9Q= modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=