Documentation
¶
Overview ¶
Package config provides subcommands for managing the eng CLI configuration. It allows users to view and modify settings stored in the $HOME/.eng.yaml file.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ConfigCmd = &cobra.Command{ Use: "config", Short: "Manage the cli's config file.", Long: `This command is used to facilitate the management of the config file specific to this cli. It should be located at $HOME/.eng.yaml`, Run: func(cmd *cobra.Command, _args []string) { headerStyle := lipgloss.NewStyle(). Bold(true). Foreground(theme.Primary). MarginBottom(1) if !ui.DisableProgress { fmt.Fprintln(log.Out, headerStyle.Render("⚙️ CLI Configuration Inspector")) } config.Email() config.DotfilesRepo() config.RepoURL() config.Branch() config.BareRepoPath() config.GitDevPath() config.GitEditor() config.Verbose() }, }
ConfigCmd represents the base command for all configuration related operations.
var DotfilesBareRepoPathCmd = &cobra.Command{ Use: "dotfiles-bare-repo-path", Short: "Update config dotfiles bare repo path", Long: `Get or set the path where the bare dotfiles repository should be stored.`, Run: func(cmd *cobra.Command, args []string) { config.BareRepoPath() }, }
DotfilesBareRepoPathCmd represents the command to manage the bare repository path configuration.
var DotfilesBranchCmd = &cobra.Command{ Use: "dotfiles-branch", Short: "Update config dotfiles branch", Long: `Get or set the dotfiles branch (main/work/server) in the configuration file.`, Run: func(cmd *cobra.Command, _args []string) { config.Branch() }, }
DotfilesBranchCmd represents the command to manage the dotfiles branch configuration.
var DotfilesRepoCmd = &cobra.Command{ Use: "dotfiles-repo", Short: "Update config dotfiles repo path", Long: `This command sets the path to the local dotfiles repository in the config file.`, Run: func(cmd *cobra.Command, args []string) { log.Start("Checking for dotfile repo path in config file...") config.DotfilesRepo() }, }
DotfilesRepoCmd defines the command for setting the local dotfiles repository path.
var DotfilesRepoURLCmd = &cobra.Command{ Use: "dotfiles-repo-url", Short: "Update config dotfiles repo URL", Long: `Get or set the dotfiles repository URL in the configuration file.`, Run: func(cmd *cobra.Command, args []string) { config.RepoURL() }, }
DotfilesRepoURLCmd represents the command to manage the dotfiles repository URL configuration.
var DotfilesTargetRepoPathCmd = &cobra.Command{ Use: "dotfiles-target-repo-path [path]", Short: "Show or set the dotfiles target repo path for copy-changes", Long: `Show or set the explicit destination git repository used by 'eng dotfiles copy-changes'. With a path argument, validates that it exists and saves it, so future copies no longer depend on dev-folder heuristics. Without arguments, prints the currently effective path and where it came from.`, Example: ` eng config dotfiles-target-repo-path eng config dotfiles-target-repo-path ~/Development/dotfiles`, Args: cobra.MaximumNArgs(1), Run: func(cmd *cobra.Command, args []string) { if len(args) > 0 { if err := config.SetTargetRepoPath(args[0]); err != nil { log.Error("%s", err) return } log.Success("Target repository path set successfully") return } if explicit := config.GetDotfilesConfig().TargetRepoPath; explicit != "" { log.Info("Target repository path (explicit config): %s", os.ExpandEnv(explicit)) return } log.Info( "No explicit target set (heuristic would resolve: %s). Pass a path to pin it.", config.TargetRepoPath(config.GetGitConfig().DevPath), ) }, }
DotfilesTargetRepoPathCmd represents the command to manage the target repository path.
var EditCmd = &cobra.Command{ Use: "edit", Short: "Interactively edit the eng CLI configuration", Long: `Launch a beautiful TUI wizard to easily update your .eng.yaml configuration settings. By default, this command launches the interactive editor. Use --interactive=false if you want to bypass the wizard in the future (though currently, the interactive editor is the primary function of this command).`, Example: ` eng config edit eng config edit --interactive`, RunE: func(cmd *cobra.Command, args []string) error { headerStyle := lipgloss.NewStyle(). Bold(true). Foreground(theme.Primary). MarginBottom(1) if !ui.DisableProgress { fmt.Fprintln(log.Out, headerStyle.Render("📝 Interactive Configuration Editor")) } if !interactiveMode { return config.RunInteractiveEditor() } return config.RunInteractiveEditor() }, }
EditCmd represents the edit command.
var EmailCmd = &cobra.Command{ Use: "email", Short: "Update config email", Long: `This command should validate and update the email config.`, Run: func(cmd *cobra.Command, args []string) { log.Start("Checking for email in config file...") config.Email() }, }
EmailCmd defines the command for setting the user's email in the configuration.
var GetCmd = &cobra.Command{ Use: "get <key>", Short: "Print a single configuration value and where it comes from", Long: `Prints one configuration value with its source (env, file, or default). Example: eng config get git.dev_path`, Args: cobra.ExactArgs(1), RunE: func(_ *cobra.Command, args []string) error { key := args[0] if _, ok := settableKeys[key]; !ok { return fmt.Errorf("unknown config key %q (run `eng config list` for known settings)", key) } v := config.NewLoader(config.ResolveConfigPath(viper.ConfigFileUsed())) rc, err := config.LoadResolved(v) if err != nil { return err } log.Message("%s=%s (source: %s)", key, resolvedValue(rc, key), rc.Source[key]) return nil }, }
GetCmd prints a single config value with its source.
var GitDevPathCmd = &cobra.Command{ Use: "git-dev-path", Short: "Update config git dev path", Long: `This command sets the path to the development folder containing git repositories in the config file.`, Run: func(cmd *cobra.Command, _args []string) { log.Start("Checking for development folder path in config file...") config.GitDevPath() }, }
GitDevPathCmd defines the command for setting the development folder path.
var GitEditorCmd = &cobra.Command{ Use: "git-editor [editor]", Aliases: []string{"editor"}, Short: "Update config default editor", Long: `Select the default editor used by the dashboard (e) from installed editors detected on PATH. You may also pass the editor command directly. The dashboard falls back to $VISUAL/$EDITOR, then agy-ide, code, and nano when no default is configured.`, Example: ` eng config git-editor eng config git-editor agy-ide eng config editor code`, Run: func(cmd *cobra.Command, args []string) { log.Start("Checking for default editor in config file...") if len(args) > 0 { config.GitEditor(args[0]) } else { config.GitEditor() } }, }
GitEditorCmd defines the command for setting the default editor.
var IdeURLCmd = &cobra.Command{ Use: "ide-url [url]", Aliases: []string{"antigravity-url", "antigravity-ide-url", "ide-download-url"}, Short: "Update Antigravity IDE download URL", Long: `This command configures the direct download URL for Antigravity IDE updates in $HOME/.eng.yaml.`, Run: func(cmd *cobra.Command, args []string) { log.Start("Checking Antigravity IDE download URL in config file...") if len(args) > 0 { config.IdeURL(args[0]) } else { config.IdeURL() } }, }
IdeURLCmd defines the command for setting the Antigravity IDE download URL.
var InitCmd = &cobra.Command{ Use: "init", Short: "Guided walkthrough to configure eng step by step", Long: `Walks through profile, git, dotfiles, proxy, and telemetry settings one section at a time, showing a preview before writing anything. Resume mid-walkthrough with --from, or preview without writing with --dry-run. Example: eng config init --from dotfiles --dry-run`, RunE: func(cmd *cobra.Command, _ []string) error { if !ui.IsTerminal(os.Stdin) || !ui.IsTerminal(os.Stdout) { return fmt.Errorf("config init requires an interactive terminal (stdin and stdout must be TTYs)") } fromStr, _ := cmd.Flags().GetString("from") dryRun, _ := cmd.Flags().GetBool("dry-run") step, err := config.ParseWizardStep(fromStr) if err != nil { return err } v := config.NewLoader(config.ResolveConfigPath(viper.ConfigFileUsed())) rc, err := config.LoadResolved(v) if err != nil { return err } changes, err := config.RunWizard(config.DefaultsFromResolved(rc), step) if err != nil { return err } rows := make([][]string, 0, len(changes)) for k, val := range changes { rows = append(rows, []string{k, fmt.Sprintf("%v", val)}) } if !ui.DisableProgress { fmt.Fprintln(log.Out, theme.InfoBox.Render("Planned changes:\n"+ui.RenderTable(ui.TableOpts{ Headers: []string{"KEY", "VALUE"}, Rows: rows, }))) } if dryRun { log.Info("Dry run: nothing written") return nil } for k, val := range changes { viper.Set(k, val) } path := config.ResolveConfigPath(viper.ConfigFileUsed()) if err := viper.WriteConfigAs(path); err != nil { return fmt.Errorf("write config: %w", err) } theme.SuccessMessage(fmt.Sprintf("Configuration saved to %s", path)) return nil }, }
InitCmd runs the guided configuration walkthrough.
var ListCmd = &cobra.Command{ Use: "list", Aliases: []string{"show", "ls"}, Short: "Display a summary of all active configuration settings", Long: `Renders a formatted overview of all current configuration keys, values, and file paths.`, Run: func(cmd *cobra.Command, _args []string) { PrintConfigSummary() }, }
ListCmd represents the config list/show command.
var MigrateCmd = &cobra.Command{ Use: "migrate", Short: "Migrate the config file to the current schema version", Long: `Migrates legacy keys to the current schema, deletes renamed keys, stamps the version, and writes a timestamped backup before changing anything. Use --check to preview without writing. Example: eng config migrate --check`, RunE: func(cmd *cobra.Command, _ []string) error { check, _ := cmd.Flags().GetBool("check") path := config.ResolveConfigPath(viper.ConfigFileUsed()) if check { data, err := os.ReadFile(path) if err != nil { return fmt.Errorf("read config: %w", err) } var decoded map[string]any if err := yaml.Unmarshal(data, &decoded); err != nil { return fmt.Errorf("parse config: %w", err) } _, changed, err := config.MigrateMap(decoded) if err != nil { return err } if unknown := config.FindUnknownKeys(path); len(unknown) > 0 { log.Warn("Unknown config keys (not read by any command): %s", strings.Join(unknown, ", ")) log.Info("Drop them with `eng config unset <key>` after confirming nothing depends on them") } if changed { log.Info("Migration needed for %s (run without --check to apply)", path) } else { theme.SuccessMessage("Configuration is already at the latest schema") } return nil } backup, changed, err := config.MigrateFile(path) if err != nil { return err } if !changed { theme.SuccessMessage("Configuration is already at the latest schema") return nil } theme.SuccessMessage(fmt.Sprintf("Migrated to schema v%d", config.CurrentVersion)) log.Info("Backup written to %s", backup) return nil }, }
MigrateCmd migrates the config file to the current schema version.
var SecretsCmd = &cobra.Command{
Use: "secrets",
Short: "Manage secret storage (bitwarden, keychain, env)",
Long: `Inspect and migrate secret storage. Tokens resolve with precedence:
env vars first, then Bitwarden items, then OS keychain accounts.
Plaintext config storage is deprecated.
Example: eng config secrets migrate --to keychain --item gitlab`,
}
SecretsCmd manages secret storage for tokens.
var SecretsMigrateCmd = &cobra.Command{ Use: "migrate", Short: "Move plaintext tokens from config into keychain or bitwarden", Long: `Moves gitlab.token from plaintext config into the chosen store, clears the plaintext key, and records the reference. Example: eng config secrets migrate --to keychain --item gitlab`, RunE: func(cmd *cobra.Command, _ []string) error { to, _ := cmd.Flags().GetString("to") item, _ := cmd.Flags().GetString("item") provider := config.SecretProvider(to) if provider != config.ProviderKeychain && provider != config.ProviderBitwarden { return fmt.Errorf("invalid --to %q (use keychain or bitwarden)", to) } if viper.GetString("gitlab.token") == "" { theme.SuccessMessage("No plaintext secrets to migrate") return nil } if err := config.MigratePlaintextToken(provider, item); err != nil { return err } theme.SuccessMessage(fmt.Sprintf("Migrated gitlab.token to %s", provider)) log.Info("Plaintext key cleared from config") return nil }, }
SecretsMigrateCmd moves plaintext tokens into a secure store.
var SetCmd = &cobra.Command{ Use: "set <key> <value>", Short: "Set a single configuration value", Long: `Sets one configuration key and validates it before writing. Keys: email, verbose, git.dev_path, git.editor, dotfiles.repo_url, dotfiles.branch, dotfiles.bare_repo_path, dotfiles.worktree_path, dotfiles.target_repo_path, containers.path, antigravity.ide_download_url. Example: eng config set email you@example.com`, Args: cobra.ExactArgs(2), RunE: func(_ *cobra.Command, args []string) error { key, value := args[0], args[1] viperKey, ok := settableKeys[key] if !ok { return fmt.Errorf("unknown config key %q (run `eng config list` for known settings)", key) } if err := validateField(key, value); err != nil { return err } var stored any = value if viperKey == "verbose" { b, err := strconv.ParseBool(value) if err != nil { return fmt.Errorf("invalid verbose %q: use true or false", value) } stored = b } viper.Set(viperKey, stored) path := config.ResolveConfigPath(viper.ConfigFileUsed()) if err := viper.WriteConfigAs(path); err != nil { return fmt.Errorf("write config: %w", err) } theme.SuccessMessage(fmt.Sprintf("Set %s", key)) log.Info("Stored in %s", path) return nil }, }
SetCmd sets a single config value, validating the field before write.
var TelemetryCmd = &cobra.Command{ Use: "telemetry", Aliases: []string{"analytics", "metrics"}, Short: "Manage OpenPanel telemetry and analytics settings", Long: `Configure anonymous telemetry reporting to your OpenPanel instance. Telemetry helps track command usage, execution performance, and reliability insights. Privacy respects: The DO_NOT_TRACK=1 and ENG_TELEMETRY_DISABLED=1 environment variables are honored globally.`, Run: func(cmd *cobra.Command, _args []string) { config.Telemetry() }, }
TelemetryCmd defines the command for managing telemetry and analytics preferences.
var UnsetCmd = &cobra.Command{ Use: "unset <key>", Short: "Remove a configuration key from the config file", Long: `Removes a top-level or dotted key from the config file entirely. Useful for dropping orphan keys flagged by validate, e.g. project_filter. Example: eng config unset project_filter`, Args: cobra.ExactArgs(1), RunE: func(_ *cobra.Command, args []string) error { key := args[0] path := config.ResolveConfigPath(viper.ConfigFileUsed()) data, err := os.ReadFile(path) if err != nil { return fmt.Errorf("read config: %w", err) } var decoded map[string]any if err := yaml.Unmarshal(data, &decoded); err != nil { return fmt.Errorf("parse config: %w", err) } if !deleteKey(decoded, key) { return fmt.Errorf("key %q not present in %s", key, path) } out, err := yaml.Marshal(decoded) if err != nil { return fmt.Errorf("encode config: %w", err) } if err := os.WriteFile(path, out, 0o600); err != nil { return fmt.Errorf("write config: %w", err) } theme.SuccessMessage(fmt.Sprintf("Removed %s", key)) return nil }, }
UnsetCmd removes a configuration key from the config file.
var ValidateCmd = &cobra.Command{ Use: "validate", Short: "Validate the resolved configuration", Long: `Loads configuration with ENG_ env overrides applied, runs central validation, and reports one actionable error per invalid field. Example: eng config validate`, RunE: func(_ *cobra.Command, _ []string) error { v := config.NewLoader(config.ResolveConfigPath(viper.ConfigFileUsed())) rc, err := config.LoadResolved(v) if err != nil { return err } errs := rc.Validate() if w := config.PlaintextSecretWarning(); w != nil { errs = append(errs, *w) } if len(errs) == 0 { theme.SuccessMessage("Configuration is valid") return nil } rows := make([][]string, 0, len(errs)) for _, fe := range errs { rows = append(rows, []string{fe.Field, fe.Value, fe.Hint}) } if !ui.DisableProgress { fmt.Fprintln(log.Out, ui.RenderTable(ui.TableOpts{ Headers: []string{"FIELD", "VALUE", "FIX"}, Rows: rows, })) } theme.ErrorMessage("Configuration has validation errors") return nil }, }
ValidateCmd checks the resolved configuration and reports field errors.
var VerboseCmd = &cobra.Command{ Use: "verbose", Short: "Update config verbose setting", Long: `This command should validate and update the verbose config setting.`, Run: func(cmd *cobra.Command, _args []string) { log.Start("Checking for verbose setting in config file...") config.Verbose() }, }
VerboseCmd defines the command for managing the verbose output setting.
Functions ¶
func PrintConfigSummary ¶ added in v1.41.0
func PrintConfigSummary()
PrintConfigSummary renders a stylized card of all current settings.
func PrintTelemetryStatus ¶ added in v1.48.0
func PrintTelemetryStatus()
PrintTelemetryStatus prints a styled summary card of telemetry configuration.
Types ¶
This section is empty.