summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOpeOginni <[email protected]>2026-02-02 06:11:25 +0100
committerGitHub <[email protected]>2026-02-01 23:11:25 -0600
commitf02499fa44ea3563fec3d0c456550b17dcef4ce5 (patch)
tree393e208f44d1f6dced0cfbf7ac2ece130e796429
parentbd9d7b3221ae144ff098c5fbb688edc75e755d3b (diff)
downloadopencode-f02499fa44ea3563fec3d0c456550b17dcef4ce5.tar.gz
opencode-f02499fa44ea3563fec3d0c456550b17dcef4ce5.zip
fix(opencode): give OPENCODE_CONFIG_CONTENT proper priority for setting config based on docs (#11670)
-rw-r--r--packages/opencode/src/config/config.ts29
1 files changed, 18 insertions, 11 deletions
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index 98970ba39..b0164e8aa 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -62,8 +62,14 @@ export namespace Config {
export const state = Instance.state(async () => {
const auth = await Auth.all()
- // Load remote/well-known config first as the base layer (lowest precedence)
- // This allows organizations to provide default configs that users can override
+ // Config loading order (low -> high precedence): https://opencode.ai/docs/config#precedence-order
+ // 1) Remote .well-known/opencode (org defaults)
+ // 2) Global config (~/.config/opencode/opencode.json{,c})
+ // 3) Custom config (OPENCODE_CONFIG)
+ // 4) Project config (opencode.json{,c})
+ // 5) .opencode directories (.opencode/agents/, .opencode/commands/, .opencode/plugins/, .opencode/opencode.json{,c})
+ // 6) Inline config (OPENCODE_CONFIG_CONTENT)
+ // Managed config directory is enterprise-only and always overrides everything above.
let result: Info = {}
for (const [key, value] of Object.entries(auth)) {
if (value.type === "wellknown") {
@@ -85,16 +91,16 @@ export namespace Config {
}
}
- // Global user config overrides remote config
+ // Global user config overrides remote config.
result = mergeConfigConcatArrays(result, await global())
- // Custom config path overrides global
+ // Custom config path overrides global config.
if (Flag.OPENCODE_CONFIG) {
result = mergeConfigConcatArrays(result, await loadFile(Flag.OPENCODE_CONFIG))
log.debug("loaded custom config", { path: Flag.OPENCODE_CONFIG })
}
- // Project config has highest precedence (overrides global and remote)
+ // Project config overrides global and remote config.
if (!Flag.OPENCODE_DISABLE_PROJECT_CONFIG) {
for (const file of ["opencode.jsonc", "opencode.json"]) {
const found = await Filesystem.findUp(file, Instance.directory, Instance.worktree)
@@ -104,12 +110,6 @@ export namespace Config {
}
}
- // Inline config content has highest precedence
- if (Flag.OPENCODE_CONFIG_CONTENT) {
- result = mergeConfigConcatArrays(result, JSON.parse(Flag.OPENCODE_CONFIG_CONTENT))
- log.debug("loaded custom config from OPENCODE_CONFIG_CONTENT")
- }
-
result.agent = result.agent || {}
result.mode = result.mode || {}
result.plugin = result.plugin || []
@@ -136,6 +136,7 @@ export namespace Config {
)),
]
+ // .opencode directory config overrides (project and global) config sources.
if (Flag.OPENCODE_CONFIG_DIR) {
directories.push(Flag.OPENCODE_CONFIG_DIR)
log.debug("loading config from OPENCODE_CONFIG_DIR", { path: Flag.OPENCODE_CONFIG_DIR })
@@ -163,6 +164,12 @@ export namespace Config {
result.plugin.push(...(await loadPlugin(dir)))
}
+ // Inline config content overrides all non-managed config sources.
+ if (Flag.OPENCODE_CONFIG_CONTENT) {
+ result = mergeConfigConcatArrays(result, JSON.parse(Flag.OPENCODE_CONFIG_CONTENT))
+ log.debug("loaded custom config from OPENCODE_CONFIG_CONTENT")
+ }
+
// Load managed config files last (highest priority) - enterprise admin-controlled
// Kept separate from directories array to avoid write operations when installing plugins
// which would fail on system directories requiring elevated permissions