Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion internal/cli/command_center.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,30 @@ type modelSummary = zerocommands.ModelSnapshot
type providerCatalogSummary = zerocommands.ProviderCatalogSnapshot

func runConfig(args []string, stdout io.Writer, stderr io.Writer, deps appDeps) int {
// The first non-flag argument is a subcommand. With no positional argument
// (or only flag arguments), the read-only summary path runs — this keeps
// `zero config` and `zero config --json` working unchanged.
command := "summary"
rest := args
if len(args) > 0 && !strings.HasPrefix(args[0], "-") {
command = strings.ToLower(strings.TrimSpace(args[0]))
rest = args[1:]
}
switch command {
case "summary":
return runConfigSummary(rest, stdout, stderr, deps)
case "notify":
return runConfigNotify(rest, stdout, stderr, deps)
case "help":
if err := writeConfigHelp(stdout); err != nil {
return exitCrash
}
return exitSuccess
}
return writeExecUsageError(stderr, fmt.Sprintf("unknown config command %q", command))
}

func runConfigSummary(args []string, stdout io.Writer, stderr io.Writer, deps appDeps) int {
options, help, err := parseCommandCenterArgs(args, false, false)
if err != nil {
return writeExecUsageError(stderr, err.Error())
Expand Down Expand Up @@ -462,8 +486,11 @@ func formatProviderCatalogValue(value string, fallback string) string {
func writeConfigHelp(w io.Writer) error {
_, err := fmt.Fprint(w, `Usage:
zero config [flags]
zero config notify [flags]

Inspects resolved Go configuration without printing secrets.
Inspects resolved Go configuration without printing secrets. The notify
subcommand reads or updates the permission-prompt alert preference —
run "zero config notify --help" for details.

Flags:
--json Print JSON summary
Expand Down
148 changes: 148 additions & 0 deletions internal/cli/config_notify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
package cli

import (
"fmt"
"io"
"strings"

"github.com/Gitlawb/zero/internal/config"
)

// runConfigNotify implements `zero config notify`: with no flags it prints the
// current mode/focusMode; --mode/--focus update them via the same
// config.SetNotify writer the TUI /notify command uses, so all surfaces stay
// in lockstep; --reset blanks both fields so the resolver defaults apply.
func runConfigNotify(args []string, stdout io.Writer, stderr io.Writer, deps appDeps) int {
options, help, err := parseConfigNotifyArgs(args)
if err != nil {
return writeExecUsageError(stderr, err.Error())
}
if help {
if err := writeConfigNotifyHelp(stdout); err != nil {
return exitCrash
}
return exitSuccess
}

resolved, exitCode := resolveCommandCenterConfig(stderr, deps)
if exitCode != exitSuccess {
return exitCode
}

if options.mode != "" || options.focus != "" || options.reset {
configPath, err := deps.userConfigPath()
if err != nil {
return writeAppError(stderr, err.Error(), exitCrash)
}
notify := config.NotifyConfig{Mode: options.mode, FocusMode: options.focus}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
if options.reset {
notify = config.NotifyConfig{}
}
if _, err := config.SetNotify(configPath, notify); err != nil {
return writeAppError(stderr, err.Error(), exitUsage)
}
// Re-resolve so the printed value reflects what the next launch will
// actually use (e.g. a reset shows the built-in defaults).
resolved, exitCode = resolveCommandCenterConfig(stderr, deps)
if exitCode != exitSuccess {
return exitCode
}
}

if options.json {
if err := writePrettyJSON(stdout, map[string]any{
"mode": resolved.Notify.Mode,
"focusMode": resolved.Notify.FocusMode,
}); err != nil {
return exitCrash
}
return exitSuccess
}
lines := []string{
"Notify",
"mode: " + displayCLIValue(resolved.Notify.Mode, "(default)"),
"focusMode: " + displayCLIValue(resolved.Notify.FocusMode, "(default)"),
}
if _, err := fmt.Fprintln(stdout, strings.Join(lines, "\n")); err != nil {
return exitCrash
}
return exitSuccess
}

type configNotifyOptions struct {
mode string
focus string
reset bool
json bool
}

func parseConfigNotifyArgs(args []string) (configNotifyOptions, bool, error) {
options := configNotifyOptions{}
for index := 0; index < len(args); index++ {
arg := args[index]
switch {
case arg == "-h" || arg == "--help" || arg == "help":
return options, true, nil
case arg == "--json":
options.json = true
case arg == "--reset":
options.reset = true
case arg == "--mode":
value, next, err := nextFlagValue(args, index, arg)
if err != nil {
return options, false, err
}
options.mode = value
index = next
case strings.HasPrefix(arg, "--mode="):
value, err := requiredInlineFlagValue(arg, "--mode")
if err != nil {
return options, false, err
}
options.mode = value
case arg == "--focus":
value, next, err := nextFlagValue(args, index, arg)
if err != nil {
return options, false, err
}
options.focus = value
index = next
case strings.HasPrefix(arg, "--focus="):
value, err := requiredInlineFlagValue(arg, "--focus")
if err != nil {
return options, false, err
}
options.focus = value
case strings.HasPrefix(arg, "-"):
return options, false, execUsageError{fmt.Sprintf("unknown flag %q", arg)}
default:
return options, false, execUsageError{fmt.Sprintf("unexpected argument %q", arg)}
}
}
return options, false, nil
}

func writeConfigNotifyHelp(w io.Writer) error {
_, err := fmt.Fprint(w, "Usage:\n"+
" zero config notify [flags]\n"+
"\n"+
"Print or update the permission-prompt notify preference.\n"+
"\n"+
"When run with no flag, prints the current mode and focusMode (the resolver\n"+
"defaults to \"both\" and \"unfocused\" when the config block is empty).\n"+
"\n"+
"Examples:\n"+
" zero config notify\n"+
" zero config notify --json\n"+
" zero config notify --mode both --focus unfocused\n"+
" zero config notify --mode off\n"+
" zero config notify --reset # clear config so the resolver defaults apply\n"+
"\n"+
"Flags:\n"+
" --mode <off|bell|notify|both> Notification mechanism\n"+
" --focus <unfocused|always|focused> When the alert fires\n"+
" --reset Clear both fields so the resolver defaults apply\n"+
" --json Machine-readable output\n"+
" -h, --help Show this help\n")
return err
}
Loading