Config#
Configuration for gptme on user-level (Global config), project-level
(Project config), and conversation-level. See Configuration for the
configuration reference.
Configuration system for gptme.
Split into sub-modules for maintainability:
models: Configuration dataclasses (ProjectConfig, UserConfig, etc.)
user: User config loading and merging
project: Project config loading and caching
chat: Chat session configuration (ChatConfig)
core: Config aggregation class, context vars, get/set/reload
cli_setup: CLI argument resolution and config initialization
- class gptme.config.AgentConfig#
Configuration for agent-specific settings.
- class gptme.config.ChatConfig#
Configuration for a chat session.
- __init__(_logdir: ~pathlib.Path | None = None, name: str | None = None, model: str | None = None, tools: list[str] | None = None, tool_format: ToolFormat | None = None, gear: int | None = None, stream: bool = True, interactive: bool = True, no_confirm: bool | None = None, max_tokens: int | None = None, temperature: float | None = None, top_p: float | None = None, workspace: ~pathlib.Path = <factory>, agent: ~pathlib.Path | None = None, system_prompt: str | None = None, env: dict = <factory>, mcp: ~gptme.config.models.MCPConfig | None = None) None#
- property agent_config: AgentConfig | None#
Get the agent configuration if available.
- classmethod from_dict(config_data: dict, *, create_workspace: bool = True) Self#
Create a ChatConfig instance from a dictionary. Warns about unknown keys.
- classmethod load_or_create(logdir: Path, cli_config: Self) Self#
Load or create a chat config, applying CLI overrides.
- save() Self#
Save the chat config to the log directory.
- Raises:
OSError – If this config was decoded by a guessed codec and its original bytes could not be backed up. The save is abandoned so the unrecoverable bytes stay on disk; only a config that already went through the legacy fallback can reach this.
- class gptme.config.Config#
A complete configuration object, including user and project configurations.
It is meant to be used to resolve configuration values, not to be passed around everywhere. Care must be taken to avoid this becoming a “god object” passed around loosely, or frequently used as a global.
- __init__(user: ~gptme.config.models.UserConfig = <factory>, project: ~gptme.config.models.ProjectConfig | None = None, chat: ~gptme.config.chat.ChatConfig | None = None, _model_source: tuple[~typing.Literal['cli', 'chat_config', 'models.default', 'MODEL'], str] | None = None) None#
- classmethod from_workspace(workspace: Path) Self#
Load the configuration from a workspace directory. Clearing any cache.
- get_env(key: str, default: str | None = None) str | None#
Gets an environment variable, checks the config file if it’s not set in the environment.
Checks both
GPTME_<KEY>and<KEY>forms for environment variables, with the prefixed form taking precedence. Config file lookups always use the bare (unprefixed) key.
- get_env_required(key: str) str#
Gets an environment variable, checks the config file if it’s not set in the environment.
Uses the same
GPTME_prefix lookup logic asget_env().
- get_plugin_config() tuple[list[Path], list[str] | None]#
Resolve plugin search paths and the enabled allowlist.
Layers user-level
[plugins](from ~/.config/gptme/config.toml) with project-level[plugins](from gptme.toml). User paths are~/absolute (or expanduser-resolved); project paths resolve against the workspace when relative. Returns(paths, enabled).The
enabledallowlist is the union of the user and project lists (empty =>None, meaning all discovered plugins are enabled). The union is intentionally restrictive: a global allowlist set by the user also constrains plugins discovered from project paths, so a project cannot silently load plugins the user hasn’t opted into. To allow a project’s plugins under a user allowlist, add them to either list.
- get_script_hooks() list[ScriptHookConfig]#
Return user and project script hooks in execution order.
- class gptme.config.ContextConfig#
Unified configuration for context management.
- Structure:
[context] enabled = true # Master switch (replaces GPTME_FRESH)
[context.selector] # Nested ContextSelectorConfig enabled = true strategy = “hybrid” max_candidates = 30 …
- __init__(enabled: bool = False, selector: ~gptme.context.selector.config.ContextSelectorConfig = <factory>, scout_model: str | None = None) None#
- classmethod from_dict(config_dict: dict[str, Any]) ContextConfig#
Create config from dictionary (typically from gptme.toml).
Example:
config = ContextConfig.from_dict({ 'enabled': True, 'scout_model': 'openai/gpt-4.1-mini', 'selector': { 'enabled': True, 'strategy': 'hybrid', 'max_candidates': 30, } })
- class gptme.config.ContextSelectorConfig#
Configuration for context selection behavior.
This configuration controls which selection strategy is used, cost limits, and strategy-specific parameters.
- __init__(enabled: bool = True, strategy: ~typing.Literal['rule', 'llm', 'hybrid'] = 'hybrid', llm_model: str = 'openai/gpt-4o-mini', max_candidates: int = 20, max_selected: int = 5, cost_limit_daily: float = 0.3, lesson_use_yaml_metadata: bool = True, lesson_priority_boost: dict[str, float] = <factory>, file_mention_weight: float = 2.0, file_recency_weight: float = 1.0) None#
- classmethod from_dict(config_dict: dict[str, Any]) ContextSelectorConfig#
Create config from dictionary (typically from gptme.toml).
- class gptme.config.HooksConfig#
Project-configured hooks.
- class gptme.config.LessonsConfig#
Configuration for the lessons system.
- class gptme.config.MCPConfig#
Configuration for Model Context Protocol support, including which MCP servers to use.
- class gptme.config.MCPServerConfig#
Configuration for a MCP server.
- class gptme.config.PluginsConfig#
Configuration for the plugin system.
- class gptme.config.ProjectConfig#
Project-level configuration, such as which files to include in the context by default.
This is loaded from a gptme.toml Project config file in the project directory or .github directory.
- __init__(_workspace: ~pathlib.Path | None = None, base_prompt: str | None = None, prompt: str | None = None, system: str | None = None, files: list[str] | None = None, exclude: list[str] = <factory>, context_cmd: str | None = None, hooks: ~gptme.config.models.HooksConfig = <factory>, rag: ~gptme.config.models.RagConfig = <factory>, agent: ~gptme.config.models.AgentConfig | None = None, lessons: ~gptme.config.models.LessonsConfig = <factory>, context: ~gptme.context.config.ContextConfig = <factory>, plugins: ~gptme.config.models.PluginsConfig = <factory>, architect: ~gptme.config.models.ArchitectConfig = <factory>, subagent: ~gptme.config.models.SubagentConfig = <factory>, settings: ~gptme.config.models.SettingsConfig = <factory>, plugin: dict[str, dict] = <factory>, env: dict[str, str] = <factory>, mcp: ~gptme.config.models.MCPConfig | None = None) None#
- class gptme.config.ProviderConfig#
Configuration for a custom OpenAI-compatible provider.
- class gptme.config.RagConfig#
Configuration for retrieval-augmented generation support.
- class gptme.config.ScriptHookConfig#
Shell command registered for an allowlisted lifecycle hook event.
- class gptme.config.SettingsConfig#
Project/user settings that affect CLI defaults.
- class gptme.config.UserConfig#
User-level configuration, such as user-specific prompts and environment variables.
- __init__(prompt: ~gptme.config.models.UserPromptConfig = <factory>, user: ~gptme.config.models.UserIdentityConfig = <factory>, env: dict[str, str] = <factory>, mcp: ~gptme.config.models.MCPConfig | None = None, providers: list[~gptme.config.models.ProviderConfig] = <factory>, lessons: ~gptme.config.models.LessonsConfig | None = None, models: ~gptme.config.models.ModelsConfig = <factory>, plugins: ~gptme.config.models.PluginsConfig = <factory>, settings: ~gptme.config.models.SettingsConfig = <factory>, hooks: ~gptme.config.models.HooksConfig = <factory>, plugin: dict[str, dict] = <factory>) None#
- class gptme.config.UserIdentityConfig#
Configuration for user identity.
- class gptme.config.UserPromptConfig#
User-level configuration for user-specific prompts and project descriptions.
- gptme.config.check_project_shell_trust(context_cmd: str | None, hook_commands: list[str], workspace: Path | None, *, interactive: bool | None = None) bool#
Gate project-level shell execution behind a TOFU trust check.
- Parameters:
context_cmd – The
context_cmdstring from the project config, or None.hook_commands – List of shell command strings from
hooks.scripts.workspace – Path to the project workspace (used as the trust scope).
interactive – Whether we are in an interactive session. If None, auto- detected from
sys.stdin.isatty().
- Returns:
True if the commands should be executed, False if they should be skipped.
- gptme.config.commands_from_project(project: ProjectConfig) tuple[str | None, list[str]]#
Return
(context_cmd, hook_commands)for a project config.Both trust-check call sites must use this so they hash the same command set.
- gptme.config.compute_shell_hash(context_cmd: str | None, hook_commands: list[str]) str#
Return
sha256:<hex>for the canonical shell content of a project config.
- gptme.config.ensure_workspace_dir(workspace: Path) None#
Create the workspace directory unless it already exists in some form.
mkdir(parents=True, exist_ok=True) only tolerates a pre-existing directory; it still raises FileExistsError when the path is a symlink or file (e.g. a manually-linked workspace). Skip creation when the path already exists in any form. is_symlink() also catches broken symlinks, which exists() reports as absent.
- gptme.config.get_project_config(workspace: Path | None, *, quiet: bool = False) ProjectConfig | None#
Get a cached copy of or load the project configuration from a gptme.toml file in the workspace or .github directory.
- Parameters:
workspace – Path to the workspace directory
quiet – If True, suppress log messages (useful for metadata lookups)
Run
reload_config()orConfig.from_workspace()to reset cache and reload the project config.
- gptme.config.is_trusted(shell_hash: str, workspace: Path | None) bool#
Return True iff shell_hash is approved for workspace.
- gptme.config.load_user_config(path: str | None = None) UserConfig#
Load the user configuration from the config file.
Also loads config.local.toml from the same directory if it exists, merging it into the main config (local values override main values). This allows committing preferences to dotfiles while keeping secrets separate.
- gptme.config.require_workspace_exists(workspace: Path) None#
Raise an actionable error if a configured workspace is missing.
Workspaces may be symlinks to external directories that later get moved or deleted. We surface a clear message instead of a bare FileNotFoundError (CLI) or a silently-dying step thread (server) when about to chdir into it.
- gptme.config.resolve_model_source(config: Config, cli_model: str | None = None, chat_model: str | None = None) tuple[str, Literal['cli', 'chat_config', 'models.default', 'MODEL']] | None#
Resolve the chat model, and which layer it came from.
Layers are ordered by specificity, mirroring
Config.get_env(): a value set for this invocation beats one set for the conversation, which beats one set for the project, which beats global user config.--model/-mCLI flagthe model saved with the conversation
GPTME_MODEL/MODELin the process environment[env].MODELin the chat config[env].MODELin the project’sgptme.toml[models].defaultin the user config[env].MODELin the user config
[models].defaultsits among the global layers, so it still beats[env].MODELin the same user config (its documented role as the formal alternative to that variable) without overriding a shell variable or a per-projectgptme.toml.The
MODELlayers are always read throughConfig.get_env(), which owns that lookup order; this function only splits it around[models].default. Layers 3-5 are the ones that outrank the default, so they are probed by masking out the layers below them, and everything left over (layer 7) comes from the plainget_envcall.Returns
Nonewhen no model is configured, leaving the caller to auto-detect from available credentials.
- gptme.config.save_provider_config(provider: ProviderConfig, reload: bool = True, local: bool = False) None#
Append a [[providers]] entry to the user config file.
- Parameters:
provider – ProviderConfig to save.
reload – Whether to reload the in-memory config after writing.
local – If True, write to config.local.toml instead of config.toml. Use for entries with inline api_key (secrets).
- Raises:
OSError – If the file was decoded by a guessed codec and its original bytes could not be backed up; nothing is written in that case.
- gptme.config.set_config_from_workspace(workspace: Path)#
Set the configuration to use a specific workspace, possibly having a project config.
- gptme.config.set_config_value(key: str, value: Any, reload: bool = True, local: bool = False) None#
Set a value in the user config file.
- Parameters:
key – Dot-separated key path (e.g. “env.ANTHROPIC_API_KEY”).
value – Value to set. Type is preserved in the TOML output.
reload – Whether to reload the in-memory config after writing.
local – If True, write to config.local.toml instead of config.toml. Use for secrets (API keys) that should not be in the shared config.
- Raises:
ValueError – If an intermediate keypath segment already exists but is not a TOML table (e.g. traversing into a string value).
OSError – If the file was decoded by a guessed codec and its original bytes could not be backed up. Nothing is written in that case, so the unrecoverable values stay on disk rather than being replaced by a possibly-garbled rewrite.
- gptme.config.setup_config_from_cli(workspace: Path, logdir: Path, model: str | None = None, tool_allowlist: str | None = None, tool_format: ToolFormat | None = None, prune_tool_output: bool | None = None, gear: int | None = None, no_confirm: bool | None = None, stream: bool = True, interactive: bool = True, agent_path: Path | None = None) Config#
Initialize and return a complete config from CLI arguments and workspace.
Model precedence is delegated to
resolve_model_source(), which orders the layers by specificity: CLI flag -> saved conversation ->MODELin the environment -> chat/project[env].MODEL->[models].default-> user[env].MODEL-> auto-detection.