summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorDax Raad <[email protected]>2025-07-11 20:50:42 -0400
committerDax Raad <[email protected]>2025-07-11 20:51:23 -0400
commit1729c310d91008e1e908109e61f32a7bbb90f5d9 (patch)
tree4dc8f4108e5277401c3f23457fdffc5fb2ddb5be
parent0130190bbddaf76afe92302bed5604aa91f3e337 (diff)
downloadopencode-1729c310d91008e1e908109e61f32a7bbb90f5d9.tar.gz
opencode-1729c310d91008e1e908109e61f32a7bbb90f5d9.zip
switch global config to ~/.config/opencode/opencode.json
-rw-r--r--packages/opencode/src/config/config.ts19
-rw-r--r--packages/web/src/content/docs/docs/config.mdx2
-rw-r--r--packages/web/src/content/docs/docs/rules.mdx2
3 files changed, 17 insertions, 6 deletions
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index 2eb12804c..196b4db83 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -4,7 +4,7 @@ import { z } from "zod"
import { App } from "../app/app"
import { Filesystem } from "../util/filesystem"
import { ModelsDev } from "../provider/models"
-import { mergeDeep } from "remeda"
+import { mergeDeep, pipe } from "remeda"
import { Global } from "../global"
import fs from "fs/promises"
import { lazy } from "../util/lazy"
@@ -175,7 +175,11 @@ export namespace Config {
export type Info = z.output<typeof Info>
export const global = lazy(async () => {
- let result = await load(path.join(Global.Path.config, "config.json"))
+ let result = pipe(
+ {},
+ mergeDeep(await load(path.join(Global.Path.config, "config.json"))),
+ mergeDeep(await load(path.join(Global.Path.config, "opencode.json"))),
+ )
await import(path.join(Global.Path.config, "config"), {
with: {
@@ -199,9 +203,10 @@ export namespace Config {
let text = await Bun.file(configPath)
.text()
.catch((err) => {
- if (err.code === "ENOENT") return "{}"
+ if (err.code === "ENOENT") return
throw new JsonError({ path: configPath }, { cause: err })
})
+ if (!text) return {}
text = text.replace(/\{env:([^}]+)\}/g, (_, varName) => {
return process.env[varName] || ""
@@ -226,7 +231,13 @@ export namespace Config {
}
const parsed = Info.safeParse(data)
- if (parsed.success) return parsed.data
+ if (parsed.success) {
+ if (!parsed.data.$schema) {
+ parsed.data.$schema = "https://opencode.ai/config.json"
+ await Bun.write(configPath, JSON.stringify(parsed.data, null, 2))
+ }
+ return parsed.data
+ }
throw new InvalidError({ path: configPath, issues: parsed.error.issues })
}
export const JsonError = NamedError.create(
diff --git a/packages/web/src/content/docs/docs/config.mdx b/packages/web/src/content/docs/docs/config.mdx
index 3c0a9f236..4e6f18c5f 100644
--- a/packages/web/src/content/docs/docs/config.mdx
+++ b/packages/web/src/content/docs/docs/config.mdx
@@ -21,7 +21,7 @@ This can be used to configure opencode globally or for a specific project.
### Global
-Place your global opencode config in `~/.config/opencode/config.json`. You'll want to use the global config for things like themes, providers, or keybinds.
+Place your global opencode config in `~/.config/opencode/opencode.json`. You'll want to use the global config for things like themes, providers, or keybinds.
---
diff --git a/packages/web/src/content/docs/docs/rules.mdx b/packages/web/src/content/docs/docs/rules.mdx
index 3249cc3f8..96b1b3938 100644
--- a/packages/web/src/content/docs/docs/rules.mdx
+++ b/packages/web/src/content/docs/docs/rules.mdx
@@ -81,7 +81,7 @@ If you have both global and project-specific rules, opencode will combine them t
## Custom Instructions
-You can specify custom instruction files in your `opencode.json` or the global `~/.config/opencode/config.json`. This allows you and your team to reuse existing rules rather than having to duplicate them to AGENTS.md.
+You can specify custom instruction files in your `opencode.json` or the global `~/.config/opencode/opencode.json`. This allows you and your team to reuse existing rules rather than having to duplicate them to AGENTS.md.
Example: