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, } }