Documentation
¶
Overview ¶
Package config — provider auto-discovery from environment.
AutoDetect scans the process environment for known API-key variables and appends corresponding [[providers]] entries so the user gets a working configuration with zero TOML editing — just set an API key and run.
Naming rule: if an env var is set and no provider with the canonical name (e.g. "groq") exists yet, AutoDetect adds it. A user's ok.toml always wins.
Package config loads OK's runtime configuration from TOML. Resolution order: flag > project ./ok.toml > user ~/.config/ok/config.toml > built-in defaults. Secrets come from the environment via api_key_env and are never stored in config files.
Index ¶
- Constants
- func ArchiveDir() string
- func AutoDetectDefaultModel(cfg *Config)
- func CommandDirs() []string
- func ConventionDirs() []string
- func DetectDefaultModel() string
- func ExpandVars(s string) string
- func MemoryUserDir() string
- func MergeModeRules(allow, ask, deny []string, policy PolicyFile) ([]string, []string, []string)
- func RenderTOML(c *Config) string
- func SessionDir() string
- func SourcePath() string
- type AgentConfig
- type CodegraphConfig
- type Config
- func (c *Config) AddPermissionRule(list, rule string) error
- func (c *Config) BashMode() string
- func (c *Config) ModeAllow() []string
- func (c *Config) ModeAsk() []string
- func (c *Config) ModeDeny() []string
- func (c *Config) ModeStyle() string
- func (c *Config) Provider(name string) (*ProviderEntry, bool)
- func (c *Config) ReadRoots() []string
- func (c *Config) RemovePermissionRule(list, rule string) (bool, error)
- func (c *Config) RemovePlugin(name string) bool
- func (c *Config) RemoveProvider(name string) error
- func (c *Config) ResolveModel(ref string) (*ProviderEntry, bool)
- func (c *Config) ResolveSystemPrompt() (string, error)
- func (c *Config) SandboxOnUnavailable() string
- func (c *Config) Save() error
- func (c *Config) SaveTo(path string) error
- func (c *Config) SetDefaultModel(name string) error
- func (c *Config) SetModeStyle(style string) error
- func (c *Config) SetPlannerModel(name string) error
- func (c *Config) SkillCustomPaths() []string
- func (c *Config) UpsertPlugin(e PluginEntry) error
- func (c *Config) UpsertProvider(e ProviderEntry) error
- func (c *Config) Validate(model string) error
- func (c *Config) WriteFile(path string) error
- func (c *Config) WriteRoots() []string
- type ECPConfig
- type ModeConfig
- type PermissionsConfigdeprecated
- type PluginEntry
- type PolicyFile
- type ProviderEntry
- type ReasonerConfig
- type RouterConfig
- type SandboxConfig
- type SkillsConfig
- type SpecialistConfig
- type TeamConfig
- type ToolsConfig
Constants ¶
const ConfigFileName = "ok.toml"
ConfigFileName is the project-level configuration file.
const DefaultSystemPrompt = `` /* 1765-byte string literal not displayed */
DefaultSystemPrompt is used when config provides none.
const DotEnvFileName = ".env"
DotEnvFileName is the project-level environment-variable file.
const LanguagePolicy = `Mirror the user's language in every reply; switch when they switch. Think ` +
`in that language. Never translate code, identifiers, file paths, shell commands, ` +
`or technical terms — keep them in their original form.`
LanguagePolicy is appended to every system prompt (in boot assembly) so the model mirrors the user's language per message instead of the harness pinning one — the UI `language` setting governs only the interface, never the model. It is static English text, so it stays part of the cache-stable prefix and keeps model behavior language-stable while still adapting the reply language.
Variables ¶
This section is empty.
Functions ¶
func ArchiveDir ¶
func ArchiveDir() string
ArchiveDir is where compacted conversation history is archived for traceability (one timestamped .jsonl per compaction). Empty if the user config directory cannot be resolved, in which case archiving is skipped.
func AutoDetectDefaultModel ¶
func AutoDetectDefaultModel(cfg *Config)
AutoDetectDefaultModel replaces cfg.DefaultModel with the first auto-detected provider that has its API key set, but only when the current default has no key configured. This lets a user who never wrote ok.toml just set an API key and run — OK picks the right model automatically.
func CommandDirs ¶
func CommandDirs() []string
CommandDirs returns the directories scanned for custom slash commands, lowest priority first, so a later (more specific) directory overrides an earlier one on a name clash. Order: home-dir convention dirs (~/.claude/commands … ~/.ok/commands), the legacy XDG user dir (~/.config/ok/commands), then the project's convention dirs (.claude/commands … .ok/commands). Scanning the .claude / .agents / .agent dirs lets commands authored for other agent tools (same .md + frontmatter format) work here unchanged.
func ConventionDirs ¶
func ConventionDirs() []string
ConventionDirs returns a copy of the asset scan directories.
func DetectDefaultModel ¶
func DetectDefaultModel() string
DetectDefaultModel returns the name of the first auto-detected provider that has its API key set. It checks profiles in order, so the default picks the most popular provider the user actually has credentials for.
Used by the CLI to give a sensible default when no config file exists and no --model flag is passed: the user just sets an API key and runs.
func ExpandVars ¶
ExpandVars substitutes ${VAR} / ${VAR:-default} references from the process environment. An unset variable with no default expands to "" (matching the MCP / Claude Code convention), so a missing secret yields an empty header rather than a literal "${TOKEN}" leaking onto the wire.
func MemoryUserDir ¶
func MemoryUserDir() string
MemoryUserDir returns the ok user config root (…/ok), under which the user-global OK.md and the per-project auto-memory store live. Empty when the user config dir can't be resolved, which disables user-scoped memory.
func MergeModeRules ¶
func MergeModeRules(allow, ask, deny []string, policy PolicyFile) ([]string, []string, []string)
func RenderTOML ¶
RenderTOML renders the config as annotated TOML in the `ok setup` house style: comments preserved, system_prompt as a multi-line string, helpful hints. The output round-trips back through Load (see render_test.go).
func SessionDir ¶
func SessionDir() string
SessionDir is where chat sessions are persisted (one .jsonl per session). Used by `ok chat --continue` / `--resume` to find the recent ones. Empty if the user config dir can't be resolved — sessions then aren't saved.
func SourcePath ¶
func SourcePath() string
SourcePath returns the highest-priority config file that exists, or "" if none.
Types ¶
type AgentConfig ¶
type AgentConfig struct {
SystemPrompt string `toml:"system_prompt"`
SystemPromptFile string `toml:"system_prompt_file"`
SystemPromptParts []string `toml:"system_prompt_parts"` // optional: extra prompt files appended in order
MaxSteps int `toml:"max_steps"`
Temperature float64 `toml:"temperature"`
PlannerModel string `toml:"planner_model"`
MaxConcurrentTasks int `toml:"max_concurrent_tasks"`
CompileCmd string `toml:"compile_cmd"`
TestCmd string `toml:"test_cmd"`
}
AgentConfig configures the harness loop. PlannerModel is optional: when set to another provider's name it enables two-model collaboration, where the planner handles low-frequency planning in its own session (kept separate so each model's prompt prefix stays cache-stable).
type CodegraphConfig ¶
CodegraphConfig governs the built-in CodeGraph MCP server — symbol/call-graph code intelligence (tree-sitter + SQLite) that gives the agent codegraph_* search / context / explore / trace / node tools. Enabled defaults to true; set enabled = false to drop those tools and fall back to grep/glob. Path overrides binary resolution; empty means the bundle shipped next to the ok executable, then a `codegraph` on PATH.
type Config ¶
type Config struct {
DefaultModel string `toml:"default_model"`
Language string `toml:"language"` // ui language tag (e.g. "zh"); empty = auto-detect from $LANG / $OK_LANG
Agent AgentConfig `toml:"agent"`
Providers []ProviderEntry `toml:"providers"`
Tools ToolsConfig `toml:"tools"`
Permissions PermissionsConfig `toml:"permissions"`
Mode ModeConfig `toml:"mode"`
Sandbox SandboxConfig `toml:"sandbox"`
Plugins []PluginEntry `toml:"plugins"`
Skills SkillsConfig `toml:"skills"`
Codegraph CodegraphConfig `toml:"codegraph"`
Team TeamConfig `toml:"team"`
Reasoner ReasonerConfig `toml:"reasoner"`
Router RouterConfig `toml:"router"`
ECP ECPConfig `toml:"ecp"`
// PluginQuiet suppresses the "auto-discovered N plugin(s)" startup notice.
PluginQuiet bool `toml:"plugin_quiet,omitempty"`
// contains filtered or unexported fields
}
Config is OK's runtime configuration.
func Default ¶
func Default() *Config
Default returns the built-in default configuration (DeepSeek + MiMo presets).
func Load ¶
Load builds the configuration: defaults, then user config, then project config, then any MCP servers from Claude Code's .mcp.json. A .env in the working directory is loaded first so api_key_env can resolve.
func LoadForEdit ¶
LoadForEdit returns a config to seed the `ok setup` wizard when reconfiguring: the built-in defaults with the file at path (if present) decoded on top, so a reconfigure preserves the user's existing providers and agent settings instead of resetting to defaults. .env is loaded so api_key_env resolution works while the wizard decides which keys are still missing.
func (*Config) AddPermissionRule ¶
AddPermissionRule appends a rule ("ToolName" or "ToolName(glob)") to the deny list (the only remaining rule list). The rule is validated with the same parser the gate uses, and a duplicate is a no-op so a UI can call it idempotently.
func (*Config) BashMode ¶
BashMode normalises the bash-sandbox mode: only an explicit "off" disables it; empty or any other value resolves to "enforce", so the sandbox is on by default and fails safe.
func (*Config) ModeDeny ¶
ModeDeny returns the effective deny rule list. [mode] takes precedence; falling back to [permissions] deny for backward compatibility.
func (*Config) ModeStyle ¶
ModeStyle returns the effective mode style ("normal" | "plan" | "yolo"). [mode] takes precedence; falling back to the old [permissions] mode for backward compatibility.
func (*Config) Provider ¶
func (c *Config) Provider(name string) (*ProviderEntry, bool)
Provider returns the named provider entry.
func (*Config) ReadRoots ¶
ReadRoots returns the directories read-only tools may access. When AllowRead is set, the roots are the workspace root plus those extras. When AllowRead is empty, ReadRoots falls back to WriteRoots(), so reads and writes share the same boundary by default.
func (*Config) RemovePermissionRule ¶
RemovePermissionRule drops the first exact match of rule from deny list, reporting whether anything was removed.
func (*Config) RemovePlugin ¶
RemovePlugin deletes the named MCP server, reporting whether it was present.
func (*Config) RemoveProvider ¶
RemoveProvider deletes the named provider. It refuses to remove the current default_model (reassign it first, so the config never points at a missing model); if the removed provider was the planner, planner_model is cleared as a side effect since it is optional. Errors when the name isn't configured.
func (*Config) ResolveModel ¶
func (c *Config) ResolveModel(ref string) (*ProviderEntry, bool)
ResolveModel resolves a model reference to a provider entry whose Model is the selected model string (a copy, so the config's lists stay intact). It accepts:
- "provider/model" — that exact model under that provider;
- a provider name — the provider's default model;
- a bare model name — the (first) provider that lists it.
The returned entry is ready to build a provider from (NewProvider reads .Model), so a single "vendor with many models" entry yields one instance per model without duplicating base_url/api_key_env. Single-`model` entries still resolve by provider name, keeping older configs working unchanged.
func (*Config) ResolveSystemPrompt ¶
ResolveSystemPrompt returns the system prompt, reading system_prompt_file if set, then appending any system_prompt_parts files in order. Resolution order:
- system_prompt_file (when non-empty) — overrides system_prompt entirely.
- system_prompt (when non-empty, and no system_prompt_file) — inline text.
- DefaultSystemPrompt — fallback when both are empty.
- system_prompt_parts files (optional) — appended after the base prompt, each joined with a blank line, so parts can add tooling guidelines, security rules, or language policies without editing the base.
func (*Config) SandboxOnUnavailable ¶
SandboxOnUnavailable returns the sandbox unavailability mode, normalising empty to "warn" so consumers don't need their own fallback logic.
func (*Config) Save ¶
Save writes the configuration back to the file it was loaded from (SourcePath), or to ./ok.toml when none exists yet — the conventional project-local target a fresh GUI session would create.
func (*Config) SaveTo ¶
SaveTo writes the configuration to path as annotated TOML, atomically: it writes a sibling temp file then renames, so a crash mid-write can't leave a half-written ok.toml that fails to parse on next load. Parent directories are created as needed.
func (*Config) SetDefaultModel ¶
permission rule list name accepted by the rule mutators. SetDefaultModel points default_model at an existing provider. It errors if no provider by that name is configured, so a UI can't strand the config on a model that doesn't exist.
func (*Config) SetModeStyle ¶
SetModeStyle sets the interaction style. Accepts "plan", "normal", or "yolo" (case-insensitive); anything else errors.
func (*Config) SetPlannerModel ¶
SetPlannerModel sets (or, with "", clears) agent.planner_model for two-model collaboration. A non-empty name must be a configured provider.
func (*Config) SkillCustomPaths ¶
SkillCustomPaths returns the configured custom skill roots with ${VAR} expanded; empty entries are dropped.
func (*Config) UpsertPlugin ¶
func (c *Config) UpsertPlugin(e PluginEntry) error
UpsertPlugin adds e, or replaces an MCP server with the same name (preserving position). The transport-specific required fields are validated: stdio needs a command, http/sse need a url.
func (*Config) UpsertProvider ¶
func (c *Config) UpsertProvider(e ProviderEntry) error
UpsertProvider adds e, or replaces an existing provider with the same name (preserving its position). Required fields (name, kind, base_url, model) are validated; whether the kind is actually registered and the key resolves is checked later by provider.New / Validate, which give actionable errors.
func (*Config) WriteRoots ¶
WriteRoots returns the directories file-writer tools may modify: the workspace root (defaulting to the current working directory when unset) plus any AllowWrite extras, with ${VAR} expanded. The roots are returned as given (relative or absolute); the confiner resolves them to absolute, symlink-free paths. The result is always non-empty, so confinement is on by default.
type ECPConfig ¶
type ECPConfig struct {
Enabled bool `toml:"enabled"`
Peers []string `toml:"peers"`
SyncInterval string `toml:"sync_interval"` // "1h", "30m", etc.
}
ECPConfig configures cross-instance knowledge federation via the Evolution Control Protocol. When Enabled, the agent shares learned skills with peers and accepts skills from them — turning single-device evolution into a federated learning network.
type ModeConfig ¶
type ModeConfig struct {
Default string `toml:"default"`
Allow []string `toml:"allow"`
Ask []string `toml:"ask"`
Deny []string `toml:"deny"`
}
ModeConfig replaces the old [permissions] section. The Default style selects "plan", "normal", or "yolo". Allow/Ask/Deny are "ToolName" or "ToolName(glob)" rule lists with precedence: deny > ask > allow.
type PermissionsConfig
deprecated
type PermissionsConfig struct {
Mode string `toml:"mode"`
Allow []string `toml:"allow"`
Ask []string `toml:"ask"`
Deny []string `toml:"deny"`
}
PermissionsConfig declares the per-call permission policy (see internal/permission). Mode is the fallback decision for writer tools when no rule matches ("ask" | "allow" | "deny"; default "ask"); read-only tools always fall back to allow. Allow/Ask/Deny are rule lists of the form "ToolName" or "ToolName(glob)". Precedence: deny > ask > allow > fallback.
Deprecated: Use ModeConfig instead. The two are mutually exclusive; if both are present, ModeConfig takes precedence.
type PluginEntry ¶
type PluginEntry struct {
Name string `toml:"name"`
Type string `toml:"type"` // "stdio" (default) | "http" | "sse"
Command string `toml:"command"`
Args []string `toml:"args"`
Env map[string]string `toml:"env"`
URL string `toml:"url"`
Headers map[string]string `toml:"headers"`
}
PluginEntry declares an external MCP server. Type selects the transport: "stdio" (default) launches Command/Args/Env as a subprocess; "http" (a.k.a. streamable-http) and "sse" connect to a remote URL with optional static Headers. String fields support ${VAR} / ${VAR:-default} expansion so secrets (bearer tokens, keys) come from the environment, not the file. The fields mirror Claude Code's mcpServers spec, so entries can come from either ok.toml's [[plugins]] or a project-root .mcp.json (see loadMCPJSON).
func (PluginEntry) ExpandedPlugin ¶
func (e PluginEntry) ExpandedPlugin() PluginEntry
ExpandedPlugin returns a copy of e with ${VAR} references expanded across the command, args, env values, url, and header values — the fields Claude Code also expands. The entry itself is left untouched.
type PolicyFile ¶
type PolicyFile struct {
Deny []string `toml:"deny"`
Allow []string `toml:"allow"`
Ask []string `toml:"ask"`
}
func LoadPolicy ¶
func LoadPolicy(homeDir string) (PolicyFile, error)
type ProviderEntry ¶
type ProviderEntry struct {
Name string `toml:"name"`
Kind string `toml:"kind"`
BaseURL string `toml:"base_url"`
Model string `toml:"model"` // a single model (back-compat)
Models []string `toml:"models"` // a vendor's model list (one base_url/key, many models)
Default string `toml:"default"` // default model when Models is set (else Models[0])
APIKeyEnv string `toml:"api_key_env"`
BalanceURL string `toml:"balance_url"` // optional; a provider-specific wallet-balance endpoint (DeepSeek: https://api.deepseek.com/user/balance). Empty = no balance readout.
ContextWindow int `toml:"context_window"`
Price *provider.Pricing `toml:"price"`
}
ProviderEntry declares a model provider instance. ContextWindow is the model's token budget; the harness compacts older history as a turn's prompt approaches it (see agent compaction). 0 disables compaction for the instance.
func AutoDetectProviders ¶
func AutoDetectProviders(existing []ProviderEntry) []ProviderEntry
AutoDetectProviders scans the environment for known API-key variables and appends any that are set and whose canonical name is not already present in cfg.Providers. It returns the (possibly extended) list so Call can choose to append it to cfg.Providers or ignore it.
A previously configured ok.toml always wins — AutoDetect only fills gaps.
func (*ProviderEntry) APIKey ¶
func (e *ProviderEntry) APIKey() string
APIKey resolves the entry's API key from its api_key_env.
func (*ProviderEntry) DefaultModel ¶
func (e *ProviderEntry) DefaultModel() string
DefaultModel returns the provider's default model: the explicit `default`, else the first of ModelList.
func (*ProviderEntry) HasModel ¶
func (e *ProviderEntry) HasModel(m string) bool
HasModel reports whether m is one of the provider's models.
func (*ProviderEntry) ModelList ¶
func (e *ProviderEntry) ModelList() []string
ModelList returns the models this provider exposes: the explicit `models` list, or the single `model` as a one-element list (back-compat). Empty if neither set.
type ReasonerConfig ¶
type ReasonerConfig struct {
DecomposeModel string `toml:"decompose_model"`
MaxConcurrent int `toml:"max_concurrent"`
}
ReasonerConfig configures the top-level multi-agent Reasoner. DecomposeModel, when set, enables LLM-based DAG decomposition. MaxConcurrent caps parallel task execution (default 3).
type RouterConfig ¶
type RouterConfig struct {
Enabled bool `toml:"enabled"`
CheapModel string `toml:"cheap_model"`
ExpensiveModel string `toml:"expensive_model"`
}
RouterConfig configures model routing by task complexity. When Enabled, CheapModel handles simple tasks and ExpensiveModel handles complex ones. DefaultModel is used for normal-complexity tasks.
type SandboxConfig ¶
type SandboxConfig struct {
WorkspaceRoot string `toml:"workspace_root"`
AllowWrite []string `toml:"allow_write"`
AllowRead []string `toml:"allow_read"`
// Bash is the OS-sandbox mode for the bash tool: "enforce" (default) jails
// each command, "off" runs it unconfined.
Bash string `toml:"bash"`
// Network allows network egress from inside the bash sandbox. Defaults true
// so module/package downloads keep working; the boundary is then writes.
Network bool `toml:"network"`
// the current platform: "warn" (default) prints a warning and continues;
// "block" refuses to run so you never operate without the sandbox.
OnUnavailable string `toml:"on_unavailable"`
}
SandboxConfig bounds the blast radius of tool calls. WorkspaceRoot is the directory file writers/readers may access; empty means the current working directory. AllowWrite lists extra dirs writers may also touch; AllowRead lists extra dirs readable beyond WorkspaceRoot (defaults to AllowWrite when unset, so reads and writes share the same boundary). Both support ${VAR} expansion.
type SkillsConfig ¶
type SkillsConfig struct {
Paths []string `toml:"paths"`
}
SkillsConfig configures skill discovery. Paths adds extra "custom"-scope skill roots — each a directory of SKILL.md / <name>.md playbooks — scanned between the project roots (.ok/.agents/.claude under the workspace) and the global roots (the same three under the home dir). ~ and relative paths and ${VAR} expansion are supported.
type SpecialistConfig ¶
type SpecialistConfig struct {
Name string `toml:"name"`
Model string `toml:"model"`
Description string `toml:"description"`
Prompt string `toml:"prompt"`
Tools []string `toml:"tools"`
}
SpecialistConfig declares one specialist in a team.
type TeamConfig ¶
type TeamConfig struct {
Orchestrator string `toml:"orchestrator"`
Specialists []SpecialistConfig `toml:"specialists"`
}
TeamConfig declares an agent team — an orchestrator model + specialist agents.
type ToolsConfig ¶
type ToolsConfig struct {
Enabled []string `toml:"enabled"`
}
ToolsConfig selects which built-in tools are enabled. Empty means all of them.