From 2d332fc6c1642e9337ff70681b68e7f5c21ef770 Mon Sep 17 00:00:00 2001 From: hems Date: Mon, 14 Jul 2025 21:58:43 +0100 Subject: [PATCH] feat(permissions): add `--yolo` flag for auto-accepting all permissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add --yolo/-y flag to enable dangerous mode that automatically accepts all permission requests - Pass yolo flag from command line through config to permission service This feature allows users to bypass all permission prompts when they trust the operations being performed, useful for automation or when running in controlled environments. 💘 Generated with Crush Co-Authored-By: Crush Co-authored-by: Andrey Nering --- cmd/root.go | 6 ++++++ internal/app/app.go | 3 ++- internal/config/config.go | 14 +++++++------- internal/permission/permission.go | 8 +++++++- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 6926255481d796b367a8678926511db8a25e74b7..ad558173c6eb1dd1bf4fdda30524ca7b04793ff5 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -45,6 +45,9 @@ to assist developers in writing, debugging, and understanding code directly from # Run a single non-interactive prompt with JSON output format crush -p "Explain the use of context in Go" -f json + + # Run in dangerous mode (auto-accept all permissions) + crush -y `, RunE: func(cmd *cobra.Command, args []string) error { // Load the config @@ -52,6 +55,7 @@ to assist developers in writing, debugging, and understanding code directly from cwd, _ := cmd.Flags().GetString("cwd") prompt, _ := cmd.Flags().GetString("prompt") quiet, _ := cmd.Flags().GetBool("quiet") + yolo, _ := cmd.Flags().GetBool("yolo") if cwd != "" { err := os.Chdir(cwd) @@ -71,6 +75,7 @@ to assist developers in writing, debugging, and understanding code directly from if err != nil { return err } + cfg.Options.SkipPermissionsRequests = yolo ctx := cmd.Context() @@ -152,6 +157,7 @@ func init() { rootCmd.Flags().BoolP("help", "h", false, "Help") rootCmd.Flags().BoolP("debug", "d", false, "Debug") rootCmd.Flags().StringP("prompt", "p", "", "Prompt to run in non-interactive mode") + rootCmd.Flags().BoolP("yolo", "y", false, "Automatically accept all permissions (dangerous mode)") // Add quiet flag to hide spinner in non-interactive mode rootCmd.Flags().BoolP("quiet", "q", false, "Hide spinner in non-interactive mode") diff --git a/internal/app/app.go b/internal/app/app.go index c3469c8cceb1bb91ff5bb1566738ea02079053a1..8a7d5ba5396a5a38c6df52b9ced3afc42da91059 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -58,12 +58,13 @@ func New(ctx context.Context, conn *sql.DB, cfg *config.Config) (*App, error) { sessions := session.NewService(q) messages := message.NewService(q) files := history.NewService(q, conn) + skipPermissionsRequests := cfg.Options != nil && cfg.Options.SkipPermissionsRequests app := &App{ Sessions: sessions, Messages: messages, History: files, - Permissions: permission.NewPermissionService(cfg.WorkingDir()), + Permissions: permission.NewPermissionService(cfg.WorkingDir(), skipPermissionsRequests), LSPClients: make(map[string]*lsp.Client), globalCtx: ctx, diff --git a/internal/config/config.go b/internal/config/config.go index 5108a5cbee1684b92f779243b35aa3a50f162e60..354005ac42f8fb1d179442353b819e871cc61259 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -114,13 +114,13 @@ type TUIOptions struct { } type Options struct { - ContextPaths []string `json:"context_paths,omitempty"` - TUI *TUIOptions `json:"tui,omitempty"` - Debug bool `json:"debug,omitempty"` - DebugLSP bool `json:"debug_lsp,omitempty"` - DisableAutoSummarize bool `json:"disable_auto_summarize,omitempty"` - // Relative to the cwd - DataDirectory string `json:"data_directory,omitempty"` + ContextPaths []string `json:"context_paths,omitempty"` + TUI *TUIOptions `json:"tui,omitempty"` + Debug bool `json:"debug,omitempty"` + DebugLSP bool `json:"debug_lsp,omitempty"` + DisableAutoSummarize bool `json:"disable_auto_summarize,omitempty"` + DataDirectory string `json:"data_directory,omitempty"` // Relative to the cwd + SkipPermissionsRequests bool `json:"-"` // Automatically accept all permissions (YOLO mode) } type MCPs map[string]MCPConfig diff --git a/internal/permission/permission.go b/internal/permission/permission.go index 2d9fca93a9e9311647287e9106f1d4f4c7b2e7e5..72dca2db9ccdb5b09ee4ff4794bbe5b51e893b40 100644 --- a/internal/permission/permission.go +++ b/internal/permission/permission.go @@ -49,6 +49,7 @@ type permissionService struct { pendingRequests sync.Map autoApproveSessions []string autoApproveSessionsMu sync.RWMutex + skip bool } func (s *permissionService) GrantPersistent(permission PermissionRequest) { @@ -77,6 +78,10 @@ func (s *permissionService) Deny(permission PermissionRequest) { } func (s *permissionService) Request(opts CreatePermissionRequest) bool { + if s.skip { + return true + } + s.autoApproveSessionsMu.RLock() autoApprove := slices.Contains(s.autoApproveSessions, opts.SessionID) s.autoApproveSessionsMu.RUnlock() @@ -125,10 +130,11 @@ func (s *permissionService) AutoApproveSession(sessionID string) { s.autoApproveSessionsMu.Unlock() } -func NewPermissionService(workingDir string) Service { +func NewPermissionService(workingDir string, skip bool) Service { return &permissionService{ Broker: pubsub.NewBroker[PermissionRequest](), workingDir: workingDir, sessionPermissions: make([]PermissionRequest, 0), + skip: skip, } }