Skip to main content

Config

Struct Config 

Source
pub struct Config {
Show 25 fields pub providers: HashMap<String, ProviderConfig>, pub models: HashMap<String, ModelConfig>, pub pricing: HashMap<String, PriceConfig>, pub agents: Vec<AgentInfo>, pub default_agent: String, pub default_model: Option<ModelConfig>, pub command_configs: HashMap<String, CommandConfig>, pub tools: ToolsConfig, pub session: SessionConfig, pub tui: TuiConfig, pub general: GeneralConfig, pub schema_version: u32, pub mcp_servers: HashMap<String, McpServerConfig>, pub lsp: LspConfig, pub permission: HashMap<String, PermissionAction>, pub commands: HashMap<String, CustomCommandConfig>, pub security: SecurityConfig, pub hooks: Vec<HookConfig>, pub memory: MemoryConfig, pub swarm: SwarmConfig, pub automation: AutomationConfig, pub notify: NotifyConfig, pub slop: SlopConfig, pub websearch: WebSearchConfig, pub system_prompt_overlays: SystemPromptOverlays,
}
Expand description

Main configuration structure

Fields§

§providers: HashMap<String, ProviderConfig>

API provider configurations

§models: HashMap<String, ModelConfig>

Model configurations

§pricing: HashMap<String, PriceConfig>

USD per million tokens, keyed "provider/model". Overrides prices learned from the provider’s /v1/models catalog.

§agents: Vec<AgentInfo>

Agent definitions

§default_agent: String

Default agent name

§default_model: Option<ModelConfig>

Default model

§command_configs: HashMap<String, CommandConfig>

Per-command configuration overrides

§tools: ToolsConfig

Tools configuration

§session: SessionConfig

Session configuration

§tui: TuiConfig

TUI configuration

§general: GeneralConfig

General settings

§schema_version: u32

On-disk schema version. Missing / 0 is migrated to CONFIG_SCHEMA_VERSION on load.

§mcp_servers: HashMap<String, McpServerConfig>

MCP server configurations

§lsp: LspConfig

Language-server overlay. Empty servers keeps built-in auto-detect.

§permission: HashMap<String, PermissionAction>

Global tool permissions (allow/ask/deny). Merged into each agent; agent-level permission.rules wins on conflict.

§commands: HashMap<String, CustomCommandConfig>

Custom slash commands keyed by name (from config.toml + markdown files)

§security: SecurityConfig

Shell command risk gating.

§hooks: Vec<HookConfig>

Pre/post tool hooks (shell commands). Empty by default.

§memory: MemoryConfig

Cross-session semantic / auto memory.

§swarm: SwarmConfig

Parallel multi-agent swarm + file conflict notify.

§automation: AutomationConfig

Background jobs and lightweight scheduling (FEATURES §11).

§notify: NotifyConfig

Discord / Telegram session notifications (off by default).

§slop: SlopConfig

Code-slop tripwires (whycodes slop / /slop). Not a training objective.

§websearch: WebSearchConfig

websearch engine choice, fallback order, and the custom endpoint.

§system_prompt_overlays: SystemPromptOverlays

Extra system-prompt text loaded from prompts/*.md (not stored in TOML).

Implementations§

Source§

impl Config

Source

pub fn project_config_path(project_dir: &Path) -> PathBuf

The project overlay: <project>/.whycodes/config.toml.

Source

pub fn to_toml_value(&self) -> Result<Value>

The whole config as a toml::Value tree, for dotted lookups.

Source

pub fn set_dotted( project_dir: &Path, target: ConfigTarget, key: &str, raw: &str, ) -> Result<PathBuf>

Set the dotted key to raw in one config file and return its path.

raw is a TOML literal (bool, number, array, inline table); text that is not one, or whose type does not fit the key, is tried as a string. Only that key changes in the file: other keys, comments and layout stay. Refused, with the file untouched, when the result does not load as a config, adds a validation error, would not change the effective value (unknown key, or a merge that keeps the lower layer), or (project) sets a key the project layer may not set. The first write to an existing file copies it to <file>.bak.

Source§

impl Config

Source

pub fn load() -> Result<Self>

Load config from the default location.

A missing file returns the OpenRouter seed without writing. Call Self::load_or_create (or Self::load_layered) to persist it. Tests and TUI dialogs that only peek at disk must not create ~/.whycodes/config.toml as a side effect.

Source

pub fn load_or_create() -> Result<Self>

Load, and on first run write the OpenRouter seed to config.toml.

Source

pub fn load_global_raw() -> Result<Self>

The global config.toml alone, as written: no project layer, no environment overlay, no ${VAR} expansion, nothing from CLI flags. A missing file is the first-run seed.

Source

pub fn update_global(edit: &mut dyn FnMut(&mut Config)) -> Result<()>

Persist one change: apply edit to Self::load_global_raw and save that. Callers keep their merged, in-memory config for the run and pass the same edit here, so values from the project layer, the environment or CLI flags never land in the global file.

Only the keys the edit changed are written: the file keeps its other keys, comments and order, and gains no defaults it did not have.

Source

pub fn migrate_schema(&mut self) -> Result<bool>

Rewrite an older config.toml in place so later loads see the current schema. Missing schema_version is treated as 0.

Source

pub fn save(&self) -> Result<()>

Save config to the default location

Source

pub fn default_path() -> Result<PathBuf>

Get default config path

Source

pub fn data_dir() -> Result<PathBuf>

Get data directory for sessions, caches, etc.

Source

pub fn load_layered(project_dir: &Path) -> Result<Self>

Load config using priority-based layering:

  1. Built-in defaults
  2. Global config (~/.whycodes/config.toml, or $WHYCODES_HOME/config.toml)
  3. Project config (<project>/.whycodes/config.toml)
  4. Environment variables (WHYCODES_*)

Returns the merged configuration.

Source

pub fn load_project_layer(project_dir: &Path) -> Option<Self>

Layer 3 of Self::load_layered on its own: <project>/.whycodes/config.toml parsed but not merged. None when the file is absent, unreadable or malformed (the last two are logged, as the layered load does).

Source

pub fn set_openrouter_api_key(&mut self, key: &str) -> Result<()>

Set an OpenRouter API key here and in the global config.toml.

Source

pub fn mark_openrouter_key_prompt_skipped(&mut self) -> Result<()>

Remember that the first-launch OpenRouter key modal was skipped.

Source

pub fn seeded_openrouter() -> Self

First-run config.toml: OpenRouter provider, no API key yet.

Source

pub fn apply_slop_file(&mut self, project_dir: &Path)

Overlay .whycodes/slop.toml when present (project-local tripwires).

Source

pub fn apply_env_overrides(&mut self)

Apply environment variable overrides to this config in-place.

Source

pub fn load_command_files(&mut self, project_dir: &Path)

Load custom commands from markdown files:

  • global: ~/.config/.../commands/*.md
  • project: <project>/.whycodes/commands/*.md
Source

pub fn load_prompt_files(&mut self, project_dir: &Path)

Load provider/model system-prompt extras from markdown:

  • global: ~/.config/.../prompts/
  • project: <project>/.whycodes/prompts/ (wins on the same key)
Source

pub fn ensure_builtin_prompt_commands(&mut self)

PromptCommands: fixed prompts that kick a turn. Does not overwrite user-defined commands.* or commands/*.md.

Source§

impl Config

Source

pub fn get_command_config(&self, command: &str) -> Option<&CommandConfig>

Get per-command configuration overrides for the given command name.

Source

pub fn expand_notify_secrets(&mut self)

Expand ${VAR} / $VAR in Discord / Telegram secret fields.

Call after layered load so config.toml can store discord_webhook = "${DISCORD_WEBHOOK_URL}" without committing the URL.

Source

pub fn substitute_vars(value: &str) -> String

Replace ${VAR_NAME} and $VAR_NAME patterns with environment variable values. Unknown variables are left as-is.

Source

pub fn project_path(&self) -> PathBuf

Get the configured project path or current directory

Source

pub fn get_provider(&self, name: &str) -> Option<&ProviderConfig>

Get provider by name

Source

pub fn get_model(&self, provider: &str, model: &str) -> Option<&ModelConfig>

Get model config

Source

pub fn configured_context_window( &self, provider: &str, model: &str, ) -> Option<u32>

Explicit context_window from config for this provider/model, if any.

Does not consult the built-in catalog — call whycodes_llm::resolve_context_window for the full chain.

Source

pub fn get_agent(&self, name: &str) -> Option<&AgentInfo>

Get agent by name

Source

pub fn default_agent(&self) -> Option<&AgentInfo>

Get the default agent

Source§

impl Config

Source

pub fn merge_with(&self, other: &Config) -> Config

Deep-merge other into self, producing a new Config.

Fields in other that are Some(_) or non-empty collections override corresponding fields in self. This implements the layering semantics where higher-priority layers win.

Source

pub fn effective_permission(&self, agent: &PermissionSet) -> PermissionSet

Merge global permission map into an agent’s PermissionSet (agent rules win).

Source§

impl Config

Source

pub fn load_stream_rule_files(&mut self, project_dir: &Path)

Merge .whycodes/rules/*.md stream rules into session.stream_rules. A file rule replaces a config-table rule of the same name.

Source§

impl Config

Source

pub fn validate(&self) -> Result<()>

Validate the configuration and return any issues.

Checks required fields and emits warnings for common misconfigurations.

Source

pub fn validation_errors(&self) -> Vec<String>

The issues Self::validate fails on (localhost base_url notes are only warnings), without logging them.

Trait Implementations§

Source§

impl Clone for Config

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Config

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Config

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Config

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for Config

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more