diff --git a/README.md b/README.md index ef33d992..71d18659 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,23 @@ yay -S infisical-bin Download binaries from [GitHub Releases](https://github.com/Infisical/cli/releases). +## Shell Completions + +The CLI can generate autocompletion scripts for bash, zsh, fish, and PowerShell via `infisical completion [shell]`. For example, to enable completions for the current session: + +```bash +# bash +source <(infisical completion bash) + +# zsh +infisical completion zsh > "${fpath[1]}/_infisical" + +# fish +infisical completion fish | source +``` + +Run `infisical completion --help` for shell-specific installation instructions (e.g. persisting completions across sessions). + ## Documentation - **[CLI Overview](https://infisical.com/docs/cli/overview)** - Complete installation and setup guide diff --git a/packages/cmd/root.go b/packages/cmd/root.go index fa103824..d8da7bcc 100644 --- a/packages/cmd/root.go +++ b/packages/cmd/root.go @@ -29,11 +29,10 @@ var ( ) var RootCmd = &cobra.Command{ - Use: "infisical", - Short: "Infisical CLI is used to inject environment variables into any process", - Long: `Infisical is a simple, end-to-end encrypted service that enables teams to sync and manage their environment variables across their development life cycle.`, - CompletionOptions: cobra.CompletionOptions{HiddenDefaultCmd: true}, - Version: util.CLI_VERSION, + Use: "infisical", + Short: "Infisical CLI is used to inject environment variables into any process", + Long: `Infisical is a simple, end-to-end encrypted service that enables teams to sync and manage their environment variables across their development life cycle.`, + Version: util.CLI_VERSION, } // rootCmdStderrWriter is a writer wrapper that dynamically reads from RootCmd.ErrOrStderr() diff --git a/packages/cmd/root_completion_test.go b/packages/cmd/root_completion_test.go new file mode 100644 index 00000000..1d639f4c --- /dev/null +++ b/packages/cmd/root_completion_test.go @@ -0,0 +1,61 @@ +package cmd + +import ( + "bytes" + "strings" + "testing" +) + +// TestCompletionCommandIsDiscoverable ensures the built-in `completion` command +// is listed in `--help` output rather than hidden, since the underlying +// generator works correctly but was previously undiscoverable. +func TestCompletionCommandIsDiscoverable(t *testing.T) { + RootCmd.InitDefaultCompletionCmd() + + cmd, _, err := RootCmd.Find([]string{"completion"}) + if err != nil { + t.Fatalf("expected to find a 'completion' subcommand, got error: %v", err) + } + if cmd.Hidden { + t.Errorf("expected 'completion' command to be visible, but it is hidden") + } + + t.Cleanup(func() { + RootCmd.SetOut(nil) + RootCmd.SetArgs(nil) + }) + + var out bytes.Buffer + RootCmd.SetOut(&out) + RootCmd.SetArgs([]string{"--help"}) + if err := RootCmd.Execute(); err != nil { + t.Fatalf("unexpected error running --help: %v", err) + } + + if !strings.Contains(out.String(), "completion") { + t.Errorf("expected 'completion' to appear in --help output, got:\n%s", out.String()) + } +} + +// TestCompletionGeneratesForAllShells verifies each supported shell produces +// a non-empty completion script without error. +func TestCompletionGeneratesForAllShells(t *testing.T) { + generators := map[string]func(*bytes.Buffer) error{ + "bash": func(buf *bytes.Buffer) error { return RootCmd.GenBashCompletionV2(buf, true) }, + "zsh": func(buf *bytes.Buffer) error { return RootCmd.GenZshCompletion(buf) }, + "fish": func(buf *bytes.Buffer) error { return RootCmd.GenFishCompletion(buf, true) }, + "powershell": func(buf *bytes.Buffer) error { return RootCmd.GenPowerShellCompletionWithDesc(buf) }, + } + + for shell, generate := range generators { + t.Run(shell, func(t *testing.T) { + var out bytes.Buffer + if err := generate(&out); err != nil { + t.Fatalf("expected no error generating %s completion, got: %v", shell, err) + } + if out.Len() == 0 { + t.Errorf("expected non-empty %s completion script", shell) + } + }) + } +}