Documentation
¶
Overview ¶
Package config holds the bee runtime configuration schema and loader.
Layered resolution: Defaults() < ~/.bee/config.toml < env vars. Profiles (tiny/normal/large) overlay budgets onto the top-level fields so the rest of the codebase only ever reads flat values.
Index ¶
- func ConfigPath() string
- func FastModelOf(c Config) string
- func IsLocalProvider(name string) bool
- func IsLoopbackURL(u string) bool
- func ResolveAutoProfile(model string) string
- func ResolveAutoProfileForProvider(provider, model string) string
- type BrowserConfig
- type BrowserVisionConfig
- type CompactionConfig
- type Config
- type MemoryConfig
- type OAuthConfig
- type Profile
- type ProfileEscalation
- type ProfileSafety
- type ProviderConfig
- type SandboxConfig
- type ShellConfig
- type UserTool
- type VisionConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ConfigPath ¶
func ConfigPath() string
ConfigPath returns the resolved path to bee's TOML config. Override with BEE_CONFIG; otherwise ~/.bee/config.toml.
func FastModelOf ¶
FastModelOf resolves the cheap side-eval model: cfg.FastModel when set, otherwise the default model.
func IsLocalProvider ¶
IsLocalProvider returns true when the named provider runs on-host. Local providers skip cost rendering, skip the auto-mode classifier, and use a 32k context floor when the model registry has no window.
func IsLoopbackURL ¶
IsLoopbackURL returns true when u points at localhost / 127.x.x.x / ::1.
func ResolveAutoProfile ¶
ResolveAutoProfile picks a profile name from a model id alone. Kept for back-compat; prefer ResolveAutoProfileForProvider so local providers (ollama / lmstudio) get the tiny surface regardless of model size.
func ResolveAutoProfileForProvider ¶
ResolveAutoProfileForProvider picks a profile name from provider + model. Local providers (ollama, lmstudio) always resolve to tiny — even a 35b local model fumbles a wide tool surface and benefits from plain-english prompts. Heuristic, not exhaustive; falls back to "normal".
Why: small local models work best with a narrow, plain-named tool set (read/bash/edit/write) described in normal english. Local runs get that surface; richer surfaces stay for frontier hosted models.
Types ¶
type BrowserConfig ¶
type BrowserConfig struct {
Enabled bool `toml:"enabled"`
Headless bool `toml:"headless"` // default false: headful so the user can watch
ChromePath string `toml:"chrome_path"` // empty -> auto-detect
Vision BrowserVisionConfig `toml:"vision"`
}
BrowserConfig gates and configures the native browser tools. Off by default to keep the tool surface lean for tiny-context profiles; flip via config or the --browser flag.
type BrowserVisionConfig ¶
type BrowserVisionConfig struct {
Model string `toml:"model"`
Endpoint string `toml:"endpoint"` // ollama base url, e.g. http://localhost:11434
}
BrowserVisionConfig points browser_screenshot at a local vision model. Model empty -> the screenshot tool is not registered.
type CompactionConfig ¶
type CompactionConfig struct {
Enabled bool `toml:"enabled"`
Threshold float64 `toml:"threshold"` // 0.0–1.0
}
CompactionConfig controls auto-summarization of long histories. Threshold is the fraction of the total context budget at which the loop auto-compacts.
type Config ¶
type Config struct {
DefaultProvider string `toml:"default_provider"`
DefaultModel string `toml:"default_model"`
// FastModel is a cheap model for side evals like /goal completion checks;
// empty => use default_model.
FastModel string `toml:"fast_model"`
Caveman string `toml:"caveman"`
Profile string `toml:"profile"`
Thinking string `toml:"thinking"` // auto | off | low | medium | high
// Mode gates how the agent reacts to user input. plan = read-only
// research + proposed plan, no mutations. edit = full tool surface
// (default). auto = side-LLM classifier picks plan|edit per turn.
Mode string `toml:"mode"` // plan | auto | edit
Sandbox SandboxConfig `toml:"sandbox"`
Shell ShellConfig `toml:"shell"`
Memory MemoryConfig `toml:"memory"`
Compaction CompactionConfig `toml:"compaction"`
Providers map[string]ProviderConfig `toml:"providers"`
Profiles map[string]Profile `toml:"profiles"`
// APIKey is the resolved key for the active provider. Populated by Load
// from os.Getenv(provider.EnvKey). Not persisted to disk.
APIKey string `toml:"-"`
// ShowBanner controls the ASCII/emoji bee logo printed at TUI startup
// AND the braille intro animation. Toggle via /settings; takes effect
// on next launch (intro is a one-shot startup animation).
ShowBanner bool `toml:"show_banner"`
// ShowLoader controls the braille "generating" animation shown while
// the model is producing the next turn (pre-token loader + animated
// caret). Default true. Toggle via /settings; persists across launches.
ShowLoader bool `toml:"show_loader"`
// MaxIterations caps tool-use rounds per Run. 0 = unlimited (loop until the
// token-budget or read-only-stall guard fires). config.Defaults() seeds 50;
// raise for tool-heavy agents, set 0 to lift the cap, lower to fail fast.
MaxIterations int `toml:"max_iterations"`
// Verbose unlocks full tool-output rendering in the TUI (compact one-line
// preview otherwise). Toggle via /settings; persists across launches.
Verbose bool `toml:"verbose"`
// ShowThoughts controls whether BlockThinking chain-of-thought is rendered
// in scrollback. Default true. Toggle via /settings; persists across launches.
ShowThoughts bool `toml:"show_thoughts"`
// ShowNudges controls whether synthetic `[nudge]` user messages — emitted
// by the loop's reasoning-only stall recovery — appear in the transcript.
// Default false (hidden). Toggle via /settings; persists across launches.
// Loop behavior is unaffected; this is a render-time filter only.
ShowNudges bool `toml:"show_nudges"`
// ShowRecap enables a one-line post-turn recap synthesized by a cheap
// side-LLM call against the freshly finished assistant message. Off by
// default (extra tokens, off-fast-path). Toggle via /settings; persists
// across launches. Disabled = no generation, no render.
ShowRecap bool `toml:"show_recap"`
// Compact strips the spacing layer from the TUI (no outer gutter, no
// blank line between turns, no user bg-tint, no OSC 133 prompt zones).
// Default false = clean mode. Set true on small terminals or for a
// denser layout. Toggle via /settings; persists across launches.
Compact bool `toml:"compact"`
// ShowContextBar reveals the thin context-fill progress strip pinned to
// the bottom edge. Default false because the bee-glyph hex fill in the
// top bar already conveys window utilisation; the bottom strip just adds
// a row of visual noise. Toggle via /settings; persists across launches.
ShowContextBar bool `toml:"show_context_bar"`
// Highlight gates syntax highlighting (chroma) on tool output, file
// content, edit/write diffs, and bash command summaries. Default true.
// Toggle via /settings; persists across launches.
Highlight bool `toml:"highlight"`
// ShellBangSilent flips the behavior of the inline shell prefix `!`.
// Default true = `!cmd` runs locally and the output is NOT forwarded to
// the LLM (silent). false restores the legacy behavior where `!cmd`
// appends its output to a user turn. `!!cmd` always runs in the
// opposite mode (escape hatch). Toggle via /settings.
ShellBangSilent bool `toml:"shell_bang_silent"`
// Editor is the command launched by ctrl+o and /edit. Empty resolves at
// runtime: $VISUAL, then $EDITOR, then vim.
Editor string `toml:"editor"`
// Top-bar chrome toggles. Default true for each preserves the original
// status-line look; flipping all five off collapses the entire top row.
// Toggle via /settings; persists across launches.
ShowBee bool `toml:"show_bee"` // 🐝 glyph
ShowContextPct bool `toml:"show_context_pct"` // "4%" next to glyph
ShowModel bool `toml:"show_model"` // provider/model label
ShowCwd bool `toml:"show_cwd"` // current working dir
ShowEffort bool `toml:"show_effort"` // "t:max" thinking level
ShowTurnTimer bool `toml:"show_turn_timer"` // ⏱ live / final elapsed
ShowGitBranch bool `toml:"show_git_branch"` // ⎇ current git branch
ShowTotalTokens bool `toml:"show_total_tokens"` // Σ session tokens (in+out)
// ExtraTools opts specific tools into the manifest beyond the active
// profile's allowlist. Names match tool Spec().Name (e.g. "apply_patch",
// "hashline_edit"). The default keeps the surface minimal; this is the
// escape hatch for power users who want expert-mode mutators without
// bumping to the `large` profile.
ExtraTools []string `toml:"extra_tools"`
// DisabledTools hides specific tools from the model regardless of profile
// allowlists. Toggled via /tools. Names match tool Spec().Name.
DisabledTools []string `toml:"disabled_tools"`
// UserTools are caller-defined shell-alias tools. Each entry registers a
// new tool whose Run executes a fixed bash command. Added via `/tools add`
// and persisted to ~/.bee/config.toml.
UserTools []UserTool `toml:"user_tools"`
// Browser gates the native chromedp-backed browser tools.
Browser BrowserConfig `toml:"browser"`
// Vision configures a fallback multimodal model. When the main model lacks
// vision, the loop routes image blocks to this model, gets text back, and
// injects it so blind models can still work with screenshots/pasted images.
Vision VisionConfig `toml:"vision"`
// UpdateCheck gates the hourly upstream-update probe.
// "ask" — probe and surface a modal when main has new commits (default)
// "auto" — probe and apply silently (notice surfaces via warn line)
// "off" — no probe, no prompt
// Picked from the modal's four buttons; persists across launches.
UpdateCheck string `toml:"update_check"`
// UpdateRepo lets forks point the probe at a different GitHub repo.
// Empty = elhenro/bee.
UpdateRepo string `toml:"update_repo"`
// UpdateBranch is the branch to compare against. Empty = main.
UpdateBranch string `toml:"update_branch"`
}
Config is the merged, post-resolution view of bee's settings. Adapters and the agent loop read from this; nothing else.
func ApplyProfile ¶
ApplyProfile overlays the active profile onto top-level Config fields that are still zero. Explicit user choices win over profile defaults; the profile only fills gaps. Also resolves c.Profile == "auto" in place so downstream code sees the concrete name. Local providers (ollama / lmstudio) skip the auto-mode classifier — c.Mode falls back to "edit" because the classifier round-trip is wasteful on slow on-host models.
type MemoryConfig ¶
type MemoryConfig struct {
Enabled bool `toml:"enabled"`
TopK int `toml:"top_k"`
BackgroundExtractor bool `toml:"background_extractor"`
}
MemoryConfig gates the heuristic memory loop. Enabled=false skips both scan and select on every turn.
type OAuthConfig ¶
type OAuthConfig struct {
ClientID string `toml:"client_id"`
AuthorizeEndpoint string `toml:"authorize_endpoint"`
TokenEndpoint string `toml:"token_endpoint"`
Scope string `toml:"scope"`
// RedirectPath defaults to /callback when empty.
RedirectPath string `toml:"redirect_path"`
// RedirectPort pins the loopback to a fixed port. Some providers only
// allow an EXACT redirect_uri match so a random port fails authorize.
// 0 = random.
RedirectPort int `toml:"redirect_port"`
// ExtraAuthorizeParams are added to the authorize URL verbatim. Use for
// vendor-specific knobs like audience, prompt, id_token_hint.
ExtraAuthorizeParams map[string]string `toml:"extra_authorize_params"`
// AccountIDHeader, when set, injects the per-account id from the saved
// token's id_token claim into this header on every request. ChatGPT
// backend requires "chatgpt-account-id".
AccountIDHeader string `toml:"account_id_header"`
// AccountIDClaim is the JWT claim name in id_token that holds the account
// id. Default for openai is "https://api.openai.com/auth" -> ".chatgpt_account_id".
AccountIDClaim string `toml:"account_id_claim"`
}
OAuthConfig configures a generic OAuth 2.0 PKCE flow for a provider. bee does not ship preconfigured client_ids for any vendor — users supply their own under [providers.<name>.oauth].
type Profile ¶
type Profile struct {
SystemPromptBudget int `toml:"system_prompt_budget"`
MemoryTopK int `toml:"memory_top_k"`
MemoryBodyChars int `toml:"memory_body_chars"` // per-memory body cap; 0 → unbounded
ToolDescChars int `toml:"tool_desc_chars"`
SkillManifestChars int `toml:"skill_manifest_chars"`
Caveman string `toml:"caveman"`
MaxIterations int `toml:"max_iterations"` // iter cap override; 0 → inherit cfg.MaxIterations; negative → unlimited
NoMutationStallThreshold int `toml:"no_mutation_stall_threshold"` // streak threshold for stall warning; 0 → off (opt-in)
// ToolFormat selects how tools are advertised. "" = native tool_calls
// channel (default); "xml" = wrap inner provider with TextModeProvider
// to inject a text-mode advert + parse `<name>{...}</name>` from the
// assistant stream. Opt-in for local/tiny models that ignore tool_calls.
ToolFormat string `toml:"tool_format"`
// ToolOutputTokens caps a single tool-result payload in token estimates
// (chars/4). 0 → fall back to per-tool default in internal/tools. Tiny
// profile uses a much smaller cap so one fat `read` doesn't blow a 4-8k
// local-model context in a single turn.
ToolOutputTokens int `toml:"tool_output_tokens"`
// SkipApplyPatch removes the apply_patch tool from the manifest. Tiny
// models mis-emit unified diffs (wrong context lines, off-by-one hunks);
// edit_diff + hashline_edit + write cover the same mutation surface
// with shapes small models hit reliably.
SkipApplyPatch bool `toml:"skip_apply_patch"`
// ReadDefaultLines is the default line slice when the model omits `lines`.
// 0 → tool's own default. Tiny uses 100 to stop one read torching the window.
ReadDefaultLines int `toml:"read_default_lines"`
// ReadMaxLines caps the largest slice a single read can return. 0 → tool default.
ReadMaxLines int `toml:"read_max_lines"`
// GrepMaxMatches caps grep result count per call. 0 → tool default.
GrepMaxMatches int `toml:"grep_max_matches"`
// Temperature / TopP pin sampling for this profile. Zero values mean
// "use provider default". Tiny pins temperature=0 (deterministic tool
// turns) with top_p=0.8 to keep 4-bit MoE outputs anchored.
Temperature float64 `toml:"temperature"`
TopP float64 `toml:"top_p"`
// ShowRecap, when non-nil, overrides Config.ShowRecap. Tiny sets false
// so the side-LLM recap round-trip doesn't double turn latency on slow
// local runs.
ShowRecap *bool `toml:"show_recap"`
// Safety carries per-profile calibration applied on top of the global
// sandbox + approval config. Tiny profile defaults to requiring the user
// to re-confirm destructive ops even after AllowSession was granted, so
// a hallucinating small model can't piggyback on one "yes" to run more
// destructive commands later. See safety.DefaultsForProfile.
Safety ProfileSafety `toml:"safety"`
// Escalation carries the optional "larger fallback model" wiring. The
// engine itself never re-enters Run with this — handoff is caller-driven
// (cmd/bee/run.go or the `bee escalate` subcommand). All fields default
// to zero / off so this is fully opt-in.
Escalation ProfileEscalation `toml:"escalation"`
}
Profile carries the small-model-friendly context budgets defined in PLAN §6b. Profile values are applied onto Config top-level fields by ApplyProfile.
func ActiveProfile ¶
ActiveProfile returns the profile named by c.Profile, falling back to "normal" and then to a zero Profile if neither exists. "auto" resolves to tiny/normal/large by provider + model class via ResolveAutoProfileForProvider.
func ScaleProfileForContext ¶
ScaleProfileForContext widens tiny-profile budgets when the active model reports a context window much larger than the tiny default. Sparse MoE models like Qwen3.6-35B-A3B-4bit advertise 128k context but the canned tiny profile pins SystemPromptBudget=3000 / ToolOutputTokens=1500, leaving ~95% of the window unused.
Heuristic: at ctxWindow > 16k, scale SystemPromptBudget to min(ctx*0.05, 8000) and ToolOutputTokens to min(ctx*0.02, 4000). Caveman ultra stays on (reasoning depth doesn't grow with context); the 4-tool surface just gets room to breathe.
Returns the input unchanged when profile isn't tiny or ctxWindow ≤ 16k. Caller passes the resolved profile name (after "auto" → "tiny" mapping).
type ProfileEscalation ¶
type ProfileEscalation struct {
// Provider id from Config.Providers. Empty = no handoff configured.
Provider string `toml:"provider"`
// Model id understood by Provider. Empty = no handoff configured.
Model string `toml:"model"`
}
ProfileEscalation configures the optional handoff path for when a tiny model wedges (two-strike) or calls the escalate tool. The model id is generic so this stays vendor-neutral.
type ProfileSafety ¶
type ProfileSafety struct {
WriteRoot string `toml:"write_root"`
ExtraSafeCommands []string `toml:"extra_safe_commands"`
RequireApprovalKeys []string `toml:"require_approval_keys"`
WarnOnDuplicateWrites bool `toml:"warn_on_duplicate_writes"`
}
ProfileSafety mirrors safety.ProfileSafety in the config schema. Kept here (rather than importing the safety package) so config has no upward dep on the safety package; defaults are seeded by safety.DefaultsForProfile via the bridge in defaults.go.
type ProviderConfig ¶
type ProviderConfig struct {
BaseURL string `toml:"base_url"`
WireAPI string `toml:"wire_api"`
EnvKey string `toml:"env_key"`
DefaultModel string `toml:"default_model"`
OAuth *OAuthConfig `toml:"oauth"` // optional; enables /login <provider>
// KeyOptional marks providers whose api key is optional (e.g. omlx run
// locally with admin-panel "skip localhost auth" enabled). When true,
// Load won't error if EnvKey is set but unresolved and no key file is
// stored — bee proceeds without an Authorization header.
KeyOptional bool `toml:"key_optional"`
// ChatTemplateKwargs flows into the MLX/vllm-extended chat completion body
// as `chat_template_kwargs`. Used to flip Qwen3 / Hermes chat-template
// switches like `enable_thinking=false` so the model emits canonical tool
// envelopes instead of prose summaries. Omitted when empty.
ChatTemplateKwargs map[string]any `toml:"chat_template_kwargs"`
}
ProviderConfig pairs a base_url with a wire_api selector. One adapter per wire format handles every OpenAI-compatible service.
type SandboxConfig ¶
type SandboxConfig struct {
Scope string `toml:"scope"`
Approval string `toml:"approval"`
CommandAllowlist []string `toml:"command_allowlist"`
}
SandboxConfig is a two-axis sandbox policy.
Scope: read-only | workspace-write | workspace-write-net | danger-full-access. Approval: untrusted | on-request | on-failure | never.
CommandAllowlist holds safety.DangerousPattern keys the user has granted AllowAlways. Loaded into the approval.Cache at startup; appended via PersistSetting when the user picks AllowAlways at a prompt.
type ShellConfig ¶
type ShellConfig struct {
UseUserRC bool `toml:"use_user_rc"`
Shell string `toml:"shell"` // override $SHELL (e.g. "/bin/zsh"); empty = autodetect
RCFile string `toml:"rc_file"` // override rc path; empty = .zshrc / .bashrc per shell
}
ShellConfig controls how the bash tool launches commands. Default keeps the hermetic `bash -c` shape (no rc files). UseUserRC=true sources the user's interactive rc file before each command so aliases and functions from .zshrc / .bashrc become available. Tradeoff: leaks rc-banner output into tool results, slower startup, breaks reproducibility — opt in only.
type UserTool ¶
type UserTool struct {
Name string `toml:"name"`
Command string `toml:"command"`
Description string `toml:"description"`
}
UserTool describes a custom shell-alias tool. Name becomes the tool id the model sees; Command is the bash command that runs on invocation. Optional arg fields let the model pass dynamic input appended to Command.
type VisionConfig ¶
type VisionConfig struct {
Model string `toml:"model"`
Endpoint string `toml:"endpoint"` // base url, e.g. http://localhost:8080/v1
API string `toml:"api"` // "openai" (default) | "ollama"
EnvKey string `toml:"env_key"` // env var holding the api key (optional for local)
// Provider, when set, inherits base_url + env_key from that configured
// [providers.<name>] entry, so a vision model served by the same backend
// as the main model needs only `provider` + `model`. Explicit Endpoint /
// EnvKey here still win.
Provider string `toml:"provider"`
}
VisionConfig points the loop's vision fallback at a multimodal model. Model empty -> no fallback: images hitting a non-vision main model are dropped with a one-time hint to configure this or run /vision. API selects the wire shape: "openai" (default — omlx/LM Studio/vLLM/hosted qwen-VL) or "ollama".