Agent Commands

# Agent commands and flags `bonnie build` compiles the agent's Go module. Commands and flags registered in `main.go` are part of that binary. No CLI manifest is needed. ## Register commands and apply parsed flags `WithCommand` gives a callback the root Cobra command and the configured agent. Callbacks run in option order, after BONNIE registers its flags and before argument parsing. They run only in `Serve`, not in `Run`. This complete `main.go` adds a journal flag and a journal inspection command: ```go package main import ( "context" "fmt" "github.com/spf13/cobra" "github.com/mark3labs/bonnie" "github.com/mark3labs/bonnie/runtime" ) func main() { bonnie.New( bonnie.WithCommand(func(root *cobra.Command, agent *bonnie.Agent) { var journal string root.PersistentFlags().StringVar(&journal, "journal", ".bonnie", "journal directory") root.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { agent.Configure(bonnie.WithJournal(journal)) return nil } root.AddCommand(&cobra.Command{ Use: "runs", Short: "List durable run IDs", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { return agent.WithJournal(cmd.Context(), func(ctx context.Context, journal runtime.Journal) error { ids, err := journal.Runs(ctx, "") if err != nil { return err } for _, id := range ids { if _, err := fmt.Fprintln(cmd.OutOrStdout(), id); err != nil { return err } } return nil }) }, }) }), ).Serve() } ``` After `bonnie build`: ```sh ./my-agent --journal ./state --addr :9090 ./my-agent --journal ./state runs ./my-agent --help ./my-agent runs --help ``` The root command still serves by default. Keep that action and the `-addr` flag to retain `bonnie dev` support. BONNIE still owns help, errors, signal handling, and process exit. - Use `root.Flags()` for serving-only flags. - Use `root.PersistentFlags()` for flags inherited by subcommands. - Use `PreRunE` for serving-only validation or configuration. - Use `PersistentPreRunE` for shared validation or configuration. Cobra's normal hook rules apply: a child hook can replace an inherited hook. - Do not call `flag.Parse()` when using `Serve`. Let Cobra parse all flags. - Prefer `--name` syntax. Root flags also accept single-dash long names, including BONNIE's `-addr`. Subcommand-local flags use normal Cobra syntax. Help runs registration callbacks, but not pre-run hooks. Keep registration free of resource setup. Multiple callbacks share the command: setting a hook replaces the previous hook unless the callback explicitly chains it. ## Configuration and context Registration runs before parsing. Use parsed values in pre-run hooks and subcommand actions, not in registration callbacks. `Agent.Configure(opts...)` applies the same options as `bonnie.New`. Options run in order; replacement and additive rules are unchanged. It does not read files or open resources. Call it before `Run`, `WithJournal`, or `WithRuntime`, including from a command's pre-run hook. Do not use it concurrently or to change a live runtime. Explicit built-in serving flags override the matching configuration before serving starts. An omitted flag does not override a configured value. Use `cmd.Context()` for blocking operations. A pre-run hook can use `cmd.SetContext` to attach application data. BONNIE passes that context to `Agent.Run`. Context data does not automatically change agent configuration or tool behavior; application code must read it. ## Scoped resource access `Agent` is configuration, not a live runner. Custom commands can open only the resources they need: | API | Resources and behavior | |---|---| | `agent.WithJournal(ctx, fn)` | Opens the configured SQLite journal and closes it after the callback. No model, factory, dotenv, prompt, sandbox check, or server setup. | | `agent.WithRuntime(ctx, fn)` | Uses the same file preparation, agent factory, and runner options as `Run`. Exposes `Runtime.Journal()` and `Runtime.Runner()`. No server, channel, schedule service, scheduler, or background cleanup starts. | `WithJournal` is suitable for run lists and history inspection. It opens the normal journal, which can create its directory and apply schema setup; it is not a read-only SQLite connection. `WithRuntime` is suitable for commands that start or resume runs through the runner's public API. It loads dotenv, resolves agent files, seeds context files, and checks the configured sandbox as serving does. Models are created by the factory when a run needs one. Both APIs return callback errors, context cancellation, and journal close errors together. A nil callback returns an error without opening resources. Do not close the supplied journal. Do not retain resource references after the callback returns. Wait for all operations and goroutines before returning. They do not intercept process signals when called outside `Serve`; the host must supply a suitable context. If a command uses `Runner.RunScheduler`, it must start, cancel, and wait for that scheduler inside the callback. Only one scheduler may own a journal at a time. Do not run an operations command that drives runs against a journal already owned by a serving process. Use the HTTP client for live-server operations instead. See [Runtime](/reference/runtime) for ownership rules.