Detailed changes
@@ -23,6 +23,7 @@ import (
"github.com/charmbracelet/crush/internal/db"
"github.com/charmbracelet/crush/internal/format"
"github.com/charmbracelet/crush/internal/history"
+ "github.com/charmbracelet/crush/internal/hooks"
"github.com/charmbracelet/crush/internal/log"
"github.com/charmbracelet/crush/internal/lsp"
"github.com/charmbracelet/crush/internal/message"
@@ -46,6 +47,7 @@ type App struct {
Permissions permission.Service
AgentCoordinator agent.Coordinator
+ HooksManager hooks.Manager
LSPClients *csync.Map[string, *lsp.Client]
@@ -89,6 +91,9 @@ func New(ctx context.Context, conn *sql.DB, cfg *config.Config) (*App, error) {
tuiWG: &sync.WaitGroup{},
}
+ // Initialize hooks manager.
+ app.HooksManager = hooks.NewManager(cfg.WorkingDir(), cfg.Options.DataDirectory, cfg.Hooks)
+
app.setupEvents()
// Initialize LSP clients in the background.
@@ -14,6 +14,7 @@ import (
"github.com/charmbracelet/catwalk/pkg/catwalk"
"github.com/charmbracelet/crush/internal/csync"
"github.com/charmbracelet/crush/internal/env"
+ "github.com/charmbracelet/crush/internal/hooks"
"github.com/invopop/jsonschema"
"github.com/tidwall/sjson"
)
@@ -326,6 +327,8 @@ type Config struct {
Tools Tools `json:"tools,omitzero" jsonschema:"description=Tool configurations"`
+ Hooks *hooks.Config `json:"hooks,omitempty" jsonschema:"description=Hook system configuration"`
+
Agents map[string]Agent `json:"-"`
// Internal
@@ -39,7 +39,6 @@ func crushGetInput(ctx context.Context, args []string) error {
// Usage: COMMAND=$(crush_get_tool_input "command")
func crushGetToolInput(ctx context.Context, args []string) error {
hc := interp.HandlerCtx(ctx)
-
if len(args) != 2 {
fmt.Fprintln(hc.Stderr, "Usage: crush_get_tool_input <param_name>")
return interp.ExitStatus(1)
@@ -3,33 +3,33 @@ package hooks
// Config defines hook system configuration.
type Config struct {
// Enabled controls whether hooks are executed.
- Enabled bool
+ Enabled bool `json:"enabled,omitempty" jsonschema:"description=Enable or disable hook execution,default=true"`
// TimeoutSeconds is the maximum time a hook can run.
- TimeoutSeconds int
+ TimeoutSeconds int `json:"timeout_seconds,omitempty" jsonschema:"description=Maximum execution time for hooks in seconds,default=30,example=30"`
// Directories are additional directories to search for hooks.
// Defaults to [".crush/hooks"] if empty.
- Directories []string
+ Directories []string `json:"directories,omitempty" jsonschema:"description=Directories to search for hook scripts,example=.crush/hooks"`
// Inline hooks defined directly in configuration.
// Map key is the hook type (e.g., "pre-tool-use").
- Inline map[string][]InlineHook
+ Inline map[string][]InlineHook `json:"inline,omitempty" jsonschema:"description=Inline hook scripts defined in configuration"`
// Disabled is a list of hook paths to skip.
// Paths are relative to the hooks directory.
// Example: ["pre-tool-use/02-slow-check.sh"]
- Disabled []string
+ Disabled []string `json:"disabled,omitempty" jsonschema:"description=List of hook paths to disable,example=pre-tool-use/02-slow-check.sh"`
// Environment variables to pass to hooks.
- Environment map[string]string
+ Environment map[string]string `json:"environment,omitempty" jsonschema:"description=Environment variables to pass to all hooks"`
}
// InlineHook is a hook defined inline in the config.
type InlineHook struct {
// Name is the name of the hook (used as filename).
- Name string
+ Name string `json:"name" jsonschema:"required,description=Name of the hook script,example=audit.sh"`
// Script is the bash script content.
- Script string
+ Script string `json:"script" jsonschema:"required,description=Bash script content to execute"`
}