Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/opencode/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,16 @@ export const layer = Layer.effect(

const loadGlobal = Effect.fnUntraced(function* () {
let result: Info = {}
// Seed the default global config with the schema for editor completion, but avoid writing when the user
// explicitly routes config through env-provided paths or content.
if (!Flag.OPENCODE_CONFIG && !Flag.OPENCODE_CONFIG_DIR && !Flag.OPENCODE_CONFIG_CONTENT) {
Comment thread
rekram1-node marked this conversation as resolved.
const file = globalConfigFile()
if (!existsSync(file)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: this check only considers config.json, opencode.json, and opencode.jsonc, so a user who still has the legacy global config file will get a new opencode.jsonc stub before the legacy migration runs. That leaves both the schema stub and migrated config.json even though a global config did exist. Consider checking path.join(Global.Path.config, "config") before seeding, or moving this after the legacy migration.

yield* fs
.writeWithDirs(file, JSON.stringify({ $schema: "https://opencode.ai/config.json" }, null, 2))
.pipe(Effect.catch(() => Effect.void))
}
}
result = mergeConfig(result, yield* loadFile(path.join(Global.Path.config, "config.json")))
result = mergeConfig(result, yield* loadFile(path.join(Global.Path.config, "opencode.json")))
result = mergeConfig(result, yield* loadFile(path.join(Global.Path.config, "opencode.jsonc")))
Expand Down
48 changes: 48 additions & 0 deletions packages/opencode/test/config/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,54 @@ test("loads config with defaults when no files exist", async () => {
})
})

test("creates global jsonc config with schema when no global configs exist", async () => {
await using tmp = await tmpdir()
const prev = Global.Path.config
;(Global.Path as { config: string }).config = tmp.path
await clear(true)

try {
await WithInstance.provide({
directory: tmp.path,
fn: async () => {
await load()
},
})

const content = await Filesystem.readText(path.join(tmp.path, "opencode.jsonc"))
expect(content).toContain('"$schema": "https://opencode.ai/config.json"')
} finally {
;(Global.Path as { config: string }).config = prev
await clear(true)
}
})

test("does not create global config when OPENCODE_CONFIG_DIR is set", async () => {
await using tmp = await tmpdir()
await using custom = await tmpdir()
const prevConfig = Global.Path.config
const prevEnv = process.env.OPENCODE_CONFIG_DIR
;(Global.Path as { config: string }).config = tmp.path
process.env.OPENCODE_CONFIG_DIR = custom.path
await clear(true)

try {
await WithInstance.provide({
directory: tmp.path,
fn: async () => {
await load()
},
})

expect(await Filesystem.exists(path.join(tmp.path, "opencode.jsonc"))).toBe(false)
} finally {
;(Global.Path as { config: string }).config = prevConfig
if (prevEnv === undefined) delete process.env.OPENCODE_CONFIG_DIR
else process.env.OPENCODE_CONFIG_DIR = prevEnv
await clear(true)
}
})

test("loads JSON config file", async () => {
await using tmp = await tmpdir({
init: async (dir) => {
Expand Down
Loading