The src/config/ module is responsible for:
Multi-Source Configuration Merging
~/.config/opencode/oh-my-opencode-slim.jsonc (preferred) or .json<directory>/.opencode/oh-my-opencode-slim.jsonc (preferred) or .jsonOH_MY_OPENCODE_SLIM_PRESETagents, tmux, fallback) are deep-merged; arrays and primitives are replacedPreset System
Subagent Delegation Rules
orchestrator: can spawn all subagents (full delegation)fixer: leaf node — prompt forbids delegationdesigner: leaf node (cannot spawn subagents)explorer, librarian, oracle: leaf nodes (cannot spawn subagents)Configuration Schema Hierarchy
PluginConfig
├── preset?: string
├── setDefaultAgent?: boolean
├── scoringEngineVersion?: 'v1' | 'v2-shadow' | 'v2'
├── balanceProviderUsage?: boolean
├── manualPlan?: ManualPlan
├── presets?: Record<string, Preset>
├── agents?: Record<string, AgentOverrideConfig>
├── disabled_mcps?: string[]
├── tmux?: TmuxConfig
├── background?: BackgroundTaskConfig
└── fallback?: FailoverConfig
AgentOverrideConfig
├── model?: string | ModelEntry[]
├── temperature?: number
├── variant?: string
├── skills?: string[] // "*" = all, "!item" = exclude
└── mcps?: string[] // "*" = all, "!item" = exclude
TmuxConfig
├── enabled: boolean
├── layout: TmuxLayout
└── main_pane_size: number
FailoverConfig
├── enabled: boolean
├── timeoutMs: number
├── retryDelayMs: number
└── chains: Record<string, string[]>
Agent Names
ORCHESTRATOR_NAME: 'orchestrator'SUBAGENT_NAMES: ['explorer', 'librarian', 'oracle', 'designer', 'fixer']ALL_AGENT_NAMES: ['orchestrator', 'explorer', 'librarian', 'oracle', 'designer', 'fixer']AGENT_ALIASES: Legacy name mappings ({ explore: 'explorer' })TypeScript Types
PluginConfig: Main configuration objectAgentOverrideConfig: Per-agent configuration overridesTmuxConfig: Tmux integration settingsTmuxLayout: Layout enum (main-horizontal, main-vertical, tiled, even-horizontal, even-vertical)Preset: Named agent configuration presetsAgentName: Union type of all agent namesMcpName: Union type of available MCPs ('websearch', 'context7', 'grep_app')BackgroundTaskConfig: Background task concurrency settingsFailoverConfig: Failover behavior configurationModelEntry: Normalized model entry with optional per-model variant ({ id: string; variant?: string })ManualAgentName: Union type for manual agent configurationManualPlan: Full manual planning configurationloadPluginConfig(directory)
│
├─→ Find user config path
│ └─→ findConfigPath(~/.config/opencode/oh-my-opencode-slim)
│ └─→ Prefers .jsonc over .json
│
├─→ Load user config with loadConfigFromPath()
│ └─→ stripJsonComments() → JSON.parse()
│ └─→ PluginConfigSchema.safeParse()
│ └─→ Returns null if invalid/missing
│
├─→ Find project config path
│ └─→ findConfigPath(<directory>/.opencode/oh-my-opencode-slim)
│
├─→ Load project config (same validation)
│
├─→ Deep merge configs (project overrides user)
│ ├─→ Top-level: project replaces user
│ └─→ Nested (agents, tmux, fallback): deepMerge()
│
├─→ Apply environment preset override
│ └─→ OH_MY_OPENCODE_SLIM_PRESET takes precedence
│
└─→ Resolve and merge preset
├─→ Find preset in config.presets[preset]
├─→ Deep merge preset agents with root agents
└─→ Warn if preset not found
deepMerge(base?, override?)
│
├─→ If base is undefined → return override
├─→ If override is undefined → return base
│
└─→ For each key in override
├─→ If both values are non-null, non-array objects
│ └─→ Recursively deepMerge
└─→ Otherwise → override replaces base
loadAgentPrompt(agentName, preset?)
│
├─→ Validate preset name (alphanumeric + underscore/dash)
│
├─→ Build prompt search dirs
│ ├─→ If preset is safe:
│ │ 1) ~/.config/opencode/oh-my-opencode-slim/{preset}
│ │ 2) ~/.config/opencode/oh-my-opencode-slim
│ └─→ Otherwise:
│ 1) ~/.config/opencode/oh-my-opencode-slim
│
├─→ Read first existing {agentName}.md from search dirs
│ └─→ If found → replacement prompt
│
└─→ Read first existing {agentName}_append.md from search dirs
└─→ If found → append prompt
External Dependencies
zod: Runtime schema validationnode:fs, node:path: File system operationsInternal Dependencies
src/cli/config-io.ts - JSONC comment stripping utility (stripJsonComments)src/cli/paths.ts - Config directory resolution (getConfigDir)Direct Consumers
src/index.ts - Main plugin entry point (imports configuration)src/agents/index.ts - Agent configuration and initializationsrc/cli/providers.ts - CLI provider resolutionsrc/config/
├── loader.ts # Config loading, merging, and prompt loading
├── schema.ts # Zod schemas and TypeScript types
└── constants.ts # Agent names, defaults, timeouts, delegation rules
POLL_INTERVAL_MS (500ms): Standard polling intervalPOLL_INTERVAL_SLOW_MS (1000ms): Slower polling for background tasksPOLL_INTERVAL_BACKGROUND_MS (2000ms): Background task pollingDEFAULT_TIMEOUT_MS (2 minutes): Default operation timeoutMAX_POLL_TIME_MS (5 minutes): Maximum polling durationFALLBACK_FAILOVER_TIMEOUT_MS (15 seconds): Failover timeoutSTABLE_POLLS_THRESHOLD (3): Number of stable polls before considering state settled| Agent | Default Model |
|---|---|
| orchestrator | runtime-resolved |
| oracle | openai/gpt-5.4 |
| librarian | openai/gpt-5.4-mini |
| explorer | openai/gpt-5.4-mini |
| designer | openai/gpt-5.4-mini |
| fixer | openai/gpt-5.4-mini |
| Parent Agent | Can Spawn |
|---|---|
| orchestrator | explorer, librarian, oracle, designer, fixer |
| fixer | (none - leaf node) |
| designer | (none - leaf node) |
| explorer | (none - leaf node) |
| librarian | (none - leaf node) |
| oracle | (none - leaf node) |
Configuration Loading
Prompt Loading
Preset Resolution
Adding New Agents
SUBAGENT_NAMES in constants.tsDEFAULT_MODELSSUBAGENT_DELEGATION_RULESschema.ts if needed (ManualPlanSchema, FallbackChainsSchema)Adding New MCPs
McpNameSchema enum in schema.tsAdding New Configuration Options
PluginConfigSchema in schema.tsloader.ts if nested object