From f9ed8bab2e633c435bb632d71b2dd3d4d142ae52 Mon Sep 17 00:00:00 2001 From: Snider Date: Sun, 1 Feb 2026 16:06:04 +0000 Subject: [PATCH] feat(dev): add confirmation prompt to apply command (#96) Add safety confirmation prompt to `core dev apply` before executing shell commands. This prevents accidental execution of destructive commands pasted from untrusted sources or generated by AI agents. Changes: - Add --yes/-y flag to skip confirmation prompt - Show warning and require explicit "y" confirmation before execution - Allow --dry-run to bypass confirmation (no actual execution) - Use existing cli.Confirm with Required() for mandatory response Usage: core dev apply --command="rm -rf ." # Prompts for confirmation core dev apply --command="..." --yes # Skips confirmation core dev apply --command="..." --dry-run # No execution, no prompt Closes #81 Co-authored-by: Claude --- pkg/dev/cmd_apply.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/pkg/dev/cmd_apply.go b/pkg/dev/cmd_apply.go index 16774370..25a9646f 100644 --- a/pkg/dev/cmd_apply.go +++ b/pkg/dev/cmd_apply.go @@ -32,6 +32,7 @@ var ( applyDryRun bool applyPush bool applyContinue bool // Continue on error + applyYes bool // Skip confirmation prompt ) // AddApplyCommand adds the 'apply' command to dev. @@ -54,6 +55,7 @@ func AddApplyCommand(parent *cli.Command) { applyCmd.Flags().BoolVar(&applyDryRun, "dry-run", false, i18n.T("cmd.dev.apply.flag.dry_run")) applyCmd.Flags().BoolVar(&applyPush, "push", false, i18n.T("cmd.dev.apply.flag.push")) applyCmd.Flags().BoolVar(&applyContinue, "continue", false, i18n.T("cmd.dev.apply.flag.continue")) + applyCmd.Flags().BoolVarP(&applyYes, "yes", "y", false, i18n.T("cmd.dev.apply.flag.yes")) parent.AddCommand(applyCmd) } @@ -101,6 +103,18 @@ func runApply() error { } cli.Blank() + // Require confirmation unless --yes or --dry-run + if !applyYes && !applyDryRun { + cli.Print("%s\n", warningStyle.Render(i18n.T("cmd.dev.apply.warning"))) + cli.Blank() + + if !cli.Confirm(i18n.T("cmd.dev.apply.confirm"), cli.Required()) { + cli.Print("%s\n", dimStyle.Render(i18n.T("cmd.dev.apply.cancelled"))) + return nil + } + cli.Blank() + } + var succeeded, skipped, failed int for _, repo := range targetRepos {