Skip to content

Rich shell autocompletion for talm CLI #170

Closed

Description

Motivation

talm CLI today ships with cobra's default completion (subcommand names, flag names) — but no value-aware completion. Every operator workflow that survives a sleepy 3am rotation involves:

  • Remembering the exact filename of the node patch (nodes/cp-01.yaml vs nodes/cp01.yaml)
  • Hand-copying node IPs / endpoints from talosconfig because the shell can't suggest them
  • Re-typing --mode=staged / --mode=try / etc. without tab-completion
  • Recalling preset names for talm init -p ...

cobra exposes everything needed to make this work out of the box. talm currently registers exactly one completion hook (pkg/commands/talosctl_wrapper.go:44 borrowing the parent's ValidArgsFunction). The cost of filling the rest is small; the daily friction relief is large.

Scope

Positional args

  • talm apply <FILE...> — complete to project files that carry the talm modeline (typically nodes/*.yaml). Scan from CWD upward to the project root (same root-detection logic that init already uses).
  • talm template <FILE...> — same set.
  • talm upgrade <FILE...> — same set.

Flag values

File-shaped flags (cobra has filename completion as a built-in directive — use it where applicable):

  • --file / -f on apply, template, upgrade — restrict to *.yaml / *.yml.
  • --values on template — restrict to *.yaml / *.yml.
  • --template / -t on template — complete to chart template paths under charts/<chart>/templates/.
  • --with-secrets on apply, template, init — *.yaml filter.
  • --talosconfig (global) — file completion.

talosconfig-derived flags:

  • --nodes (global) — parse the in-scope talosconfig (--talosconfig value, $TALOSCONFIG, default ~/.talos/config, project-local talosconfig), extract every node from every context, dedup, return.
  • --endpoints (global) — same source, endpoint fields.

Lazy: only resolve talosconfig when the flag is actually being completed.

Enum flags:

  • --mode on apply — {auto, no-reboot, reboot, staged, try} from helpers.Mode's known set.
  • --preset / -p on init — enum of valid preset names (currently embedded in talm's preset registry).
  • --talos-version on apply / template / init / upgrade — known machinery contract values (v1.10, v1.11, v1.12, ...) parsed from siderolabs/talos/pkg/machinery/config.

Out of scope (initial phase)

  • --set / --set-string / --set-json / --set-literal / --set-file value completion (would need to introspect values.yaml schema — large enough for its own follow-up).
  • Dynamic image-tag completion for --image (would require a network call).

Design

cobra API used per category:

  • File-shaped flags: cmd.RegisterFlagCompletionFunc(name, func) with the []string{"yaml", "yml"} filter via cobra.ShellCompDirectiveFilterFileExt.
  • Positional args with modeline filter: cmd.ValidArgsFunction = func(cmd, args, toComplete) ([]string, cobra.ShellCompDirective) — walk CWD-to-project-root, list *.yaml, filter to files whose head matches the talm modeline regex (already implemented in processModelineAndUpdateGlobals).
  • talosconfig-derived: cmd.RegisterFlagCompletionFunc("nodes", ...) and parse with the existing talosconfig loader.
  • Static enums: cobra.FixedCompletions([]string{"auto", "no-reboot", ...}, cobra.ShellCompDirectiveNoFileComp).

Where it lives

One file per command: pkg/commands/apply_completion.go, template_completion.go, etc. Each init() (or an explicit registerCompletions(cmd) called from the command's init()) attaches its completions. Keeps completion co-located with the command, avoids a god-file.

The shared talosconfig parser (nodes + endpoints extraction) goes in pkg/commands/completion_helpers.go since multiple commands need it.

Tests

cobra completion functions are pure: (cmd, args, toComplete) -> ([]string, ShellCompDirective). Unit-test each:

  • pkg/commands/apply_completion_test.go — feed fixtures for --mode, --nodes (with a fake talosconfig), positional file argument (with a fake CWD layout), assert returned values + directive.
  • Per-shell smoke test (optional): pipe talm completion bash into bash -n to prove the generated script parses; skip in CI if it adds too much.

How users enable it

Nothing new on the talm side — completion is on once talm completion <shell> is sourced:

# bash
talm completion bash | source
# zsh
talm completion zsh > "${fpath[1]}/_talm"
# fish
talm completion fish | source
# powershell
talm completion powershell | Out-String | Invoke-Expression

cobra already generates talm completion <shell> for free — confirm it's present in pkg/commands/root.go, add if missing.

Acceptance

  • All four shells (bash, zsh, fish, powershell) emit completion scripts via talm completion <shell> and the scripts parse.
  • Unit tests cover each completion func with realistic input.
  • README gets a small "Shell completion" section pointing at talm completion --help.

Activity

  1. added
    kind/featureCategorizes issue or PR as related to a new feature
    area/commandsIssues or PRs related to pkg/commands (CLI subcommands, flag parsing, root detection)
    on May 11, 2026
  2. added 14 commits that reference this issue on May 13, 2026
    d14fa5e
    7e45f4c
    edf9a73
    48aefee
    f9fab44
    8e1ca6d
    979d6d3
    7c40bdf
    43bcc59
    df0b433
    3945cf2
    a24ef9f
    a37a668
    f5b6d80
  3. lexfrei commented on May 14, 2026

    @lexfrei
    ContributorAuthor

    Resolved by #204 (merged into main as a0301e7).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/commandsIssues or PRs related to pkg/commands (CLI subcommands, flag parsing, root detection)kind/featureCategorizes issue or PR as related to a new feature

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions