banger/internal/cli/commands_ssh_config.go
Thales Maciel 35bfac3f13
cli: rewrite help text for AI-driven discovery
Frontier models tend to discover a CLI by running --help, scanning
the Long description, and inferring the dominant workflow from the
examples. Today's banger help reads like a man page index — every
verb has a one-line Short and nothing else. This rewrites the
groups (banger, vm, vm workspace, image, kernel, system,
ssh-config) so each landing page answers "what is this for, what's
the 80% command, what comes next" in three to ten lines, with
runnable examples.

Also disambiguates the near-twin lifecycle commands so a model
reading the subcommand index can tell stop/kill/delete apart at a
glance:

  start    Start a stopped VM
  stop     Stop a running VM gracefully
  restart  Stop then start a VM
  kill     Force-kill a VM (use when 'vm stop' hangs)
  delete   Stop a VM and remove its disks (irreversible)

vm create / vm ssh / vm logs / vm show pick up Long descriptions
and examples for the same reason. No behaviour changes; help text
only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 15:02:08 -03:00

102 lines
3.3 KiB
Go

package cli
import (
"fmt"
"strings"
"banger/internal/config"
"banger/internal/daemon"
"banger/internal/paths"
"github.com/spf13/cobra"
)
// newSSHConfigCommand exposes the opt-in ergonomics for `ssh <name>.vm`.
// Default mode prints current status + the exact Include line the user
// can paste into ~/.ssh/config themselves. --install does the include
// for them inside a marker-fenced block; --uninstall reverses it.
func newSSHConfigCommand() *cobra.Command {
var (
install bool
uninstall bool
)
cmd := &cobra.Command{
Use: "ssh-config",
Short: "Enable plain 'ssh <name>.vm' from any terminal",
Long: `Banger keeps a self-contained SSH client config under its own config
directory (never touching ~/.ssh/config on its own). Opt in to the
convenience shortcut that lets you run 'ssh <name>.vm' from any
terminal, bypassing 'banger vm ssh':
banger ssh-config # print status + copy-paste snippet
banger ssh-config --install # add an Include line to ~/.ssh/config
banger ssh-config --uninstall # remove banger's Include from ~/.ssh/config
After --install, 'ssh agent.vm' works the same as 'banger vm ssh
agent', including for tools like rsync, scp, and editor remotes.
`,
Example: strings.TrimSpace(`
banger ssh-config --install
ssh agent.vm
rsync -avz ./code agent.vm:/root/repo/
`),
Args: noArgsUsage("usage: banger ssh-config [--install|--uninstall]"),
RunE: func(cmd *cobra.Command, args []string) error {
if install && uninstall {
return fmt.Errorf("use only one of --install or --uninstall")
}
layout, err := paths.Resolve()
if err != nil {
return err
}
cfg, err := config.Load(layout)
if err != nil {
return err
}
if err := daemon.SyncVMSSHClientConfig(layout, cfg.SSHKeyPath); err != nil {
return err
}
bangerConfig := daemon.BangerSSHConfigPath(layout)
switch {
case install:
if err := daemon.InstallUserSSHInclude(layout); err != nil {
return err
}
_, err = fmt.Fprintf(cmd.OutOrStdout(),
"added Include %s to ~/.ssh/config — `ssh <name>.vm` will now route through banger\n",
bangerConfig,
)
return err
case uninstall:
if err := daemon.UninstallUserSSHInclude(); err != nil {
return err
}
_, err = fmt.Fprintln(cmd.OutOrStdout(), "removed banger's entries from ~/.ssh/config")
return err
default:
installed, err := daemon.UserSSHIncludeInstalled()
if err != nil {
return err
}
out := cmd.OutOrStdout()
fmt.Fprintf(out, "banger ssh_config: %s\n", bangerConfig)
if installed {
fmt.Fprintln(out, "status: included from ~/.ssh/config")
fmt.Fprintln(out, "")
fmt.Fprintln(out, "`ssh <name>.vm` is enabled. Run `banger ssh-config --uninstall` to revert.")
} else {
fmt.Fprintln(out, "status: not included (opt-in)")
fmt.Fprintln(out, "")
fmt.Fprintln(out, "Enable `ssh <name>.vm` in two ways:")
fmt.Fprintln(out, " banger ssh-config --install")
fmt.Fprintln(out, "or add this line to ~/.ssh/config yourself:")
fmt.Fprintf(out, " Include %s\n", bangerConfig)
}
return nil
}
},
}
cmd.Flags().BoolVar(&install, "install", false, "add an Include line to ~/.ssh/config")
cmd.Flags().BoolVar(&uninstall, "uninstall", false, "remove banger's Include from ~/.ssh/config")
return cmd
}