bonsai

Configuration

bonsai reads a layered .bonsai/config.toml — edit the file and relaunch (or /config validate to check it in place first). Config is the substrate the extensibility surfaces build on: MCP servers, hooks, the sandbox posture, and verification commands. You can also just ask bonsai — the built-in customize and provider-setup skills teach the agent every extension surface, with CI-checked examples.

Layering

Two files, merged with everything else in a fixed precedence:

CLI > env > .env > project > global > defaults

Merge rules per section:

Section Rule
[mcp.servers.<name>] keyed by name, whole-entry replace — a project entry replaces a same-named global one wholesale
[[hooks]] concatenated global-first then project, in fire order; a same-named project hook shadows the global one (so enabled = false in the project disables a global hook)
[sandbox] writable_roots union; deny_network scalar, higher layer wins
[verification] test/build whole-list, higher layer wins; same for after_edit

Fault tolerance

Loading is per-entry resilient: one malformed [mcp.servers.x] or [[hooks]] table degrades to a diagnostic naming the entry and field, and the rest of the file still applies. Only a file that fails TOML parsing entirely drops the whole layer. Unknown top-level keys are ignored with a forward-compatibility note; skills, commands, and providers are reserved for future releases. schema_version = 1 guards forward compatibility — a file written by a newer bonsai loads best-effort with a warning. See the compatibility contract.

The schema

Every top-level section is optional; a file states only what it overrides.

schema_version = 1

[sandbox]
deny_network = true       # default posture; false allows network in the sandbox
writable_roots = []       # extra paths, unioned with BONSAI_SANDBOX_WRITABLE_ROOTS

[verification]
# Omit a lane to detect it from project manifests; an empty list disables it.
test = ["cargo test --locked"]
build = ["cargo build --release --locked"]
after_edit = "off"        # off (default) | ask | on

[mcp.servers.<name>]      # see docs/mcp.md for the full field reference
transport = "stdio"       # or "http"
command = "npx"           # stdio: command/args/env/cwd
# url = "https://…"       # http: url/headers/oauth_client_id/oauth_scopes
enabled = true
allow_tools = []          # empty = every discovered tool
capabilities = []         # read/write/network/shell/irreversible/untrusted_output
batching = "serialized"   # or "path_scoped"
timeout_secs = 30

[[hooks]]                 # see docs/hooks.md for the full field reference
name = "cargo-fmt"
event = "PostFileWrite"   # SessionStart/SessionEnd/Pre|PostToolUse/Pre|PostFileWrite/Pre|PostBash
matcher = { path = "**/*.rs" }          # and/or { tool = "<glob>" }
action = { type = "shell", command = "cargo fmt -- \"$BONSAI_FILE_PATH\"" }
timeout_secs = 30
blocking = false
on_failure = "warn"       # or "block" (fail-closed, blocking pre-events only)
enabled = true

Verification

/test and /build run the configured (or manifest-detected) command profiles through the agent’s normal bash permission, sandbox, hook, cancellation, and transcript-evidence path. Cargo, Node package scripts, Go modules, and Python projects are detected from their manifests in stable order; a Cargo.lock adds --locked. after_edit = "on" runs the test profile once after a coding turn that changed workspace state (falling back to build when no tests exist); "ask" prompts in the TUI and skips on noninteractive surfaces. In headless mode, bonsai -p /test or -p /build expands to the same bounded workflow, and stale, failed, interrupted, or incomplete verification exits non-zero.

/config commands

Resource directories

Beyond config.toml, bonsai discovers file-based resources from conventional directories, highest precedence first:

  1. <project>/.bonsai/<kind>/
  2. <project>/.claude/<kind>/ (cross-tool compatibility)
  3. <project>/.agents/<kind>/ (cross-tool compatibility)
  4. $BONSAI_HOME/<kind>/ (global)

where <kind> is agents/ (flat <name>.mdcustom agents), skills/ (<name>/SKILL.mdskills), themes/ (flat <name>.tomltheming), and memory/ (memory, .bonsai + $BONSAI_HOME only). A project resource shadows a global (and built-in) one of the same name; within a project, .bonsai > .claude > .agents. A .disabled file (one name per line) in any resource directory suppresses entries — this is how built-in skills are disabled per project. Project resources require workspace trust.

Provider and model catalog overrides live in $BONSAI_HOME/providers|models and .bonsai/providers|models — see Providers and Models.

Environment variables

The complete environment surface, grouped. Per-provider credential/model/URL variables are listed in Providers.

Variable Purpose
BONSAI_HOME Home directory (default ~/.bonsai)
BONSAI_CONFIG Replace the project config path
BONSAI_DOTENV 0/false/off/no disables .env loading
BONSAI_PROVIDER Provider for a new headless run
BONSAI_AUTONOMY Startup autonomy level
BONSAI_SELF_REVIEW auto\|on\|ask\|off startup self-review mode
BONSAI_EPISODES 0/false/off/no/disabled disables task episodes
BONSAI_SANDBOX, BONSAI_SANDBOX_NETWORK, BONSAI_SANDBOX_WRITABLE_ROOTS Sandbox posture
BONSAI_MAX_GENERATION_SECONDS, BONSAI_MAX_STREAMED_CHARS Per-attempt generation caps
BRAVE_SEARCH_API_KEY/BRAVE_API_KEY, TAVILY_API_KEY, BONSAI_SEARXNG_URL, BONSAI_WEB_SEARCH_PROVIDER Web search
BONSAI_RUST_ANALYZER, BONSAI_TYPESCRIPT_LANGUAGE_SERVER, BONSAI_PYRIGHT_LANGSERVER, BONSAI_GOPLS Language-server command overrides
BONSAI_MEMORY_EMBEDDINGS off keeps memory retrieval BM25-only
BONSAI_MODELS_DEV_URL / _PATH / _TTL_SECS, BONSAI_DISABLE_MODELS_FETCH Model catalog source
BONSAI_CODEX_CLIENT_VERSION, BONSAI_CODEX_REASONING_PERSIST Codex transport tuning
BONSAI_COLOR_MODE, NO_COLOR Terminal color
BONSAI_LOG / RUST_LOG Tracing verbosity (defaults warn)
BONSAI_TRANSCRIPT_LOG Write every request/response to disk (debugging; large)
BONSAI_SYMBOL_RESPECT_GITIGNORE, BONSAI_REPO_MAP_RESPECT_GITIGNORE Symbol/repo-map gitignore handling

/settings

/settings covers the main runtime preferences without file editing: model, autonomy, self-review, context (smol), default credential store, appearance (serenity, theme), per-run budgets (max turns, run time, generation, output, tool time), session budgets (turns, output, time, cost), and sandbox (confinement, network). Every budget is off by default; choosing a preset opts in, and command-line limits still override saved values for that run. Preferences persist in the local database, not in config.toml.

Where this lives in the code

Concern Location
Load, layering, diagnostics src/config/mod.rs
Schema types src/config/schema.rs
Merge rules src/config/merge.rs
Validation src/config/validate.rs
/config command src/commands/config_cmd.rs
Resource discovery src/resource/discovery.rs