From 7e9050edb97dfb24818ac8ca9dad08eec0b2bbcc Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Thu, 31 Jul 2025 06:25:26 -0500 Subject: [PATCH] feat: jsonc configuration file support (#1434) --- bun.lock | 1 + packages/opencode/package.json | 1 + packages/opencode/src/cli/error.ts | 6 +++++- packages/opencode/src/config/config.ts | 21 ++++++++++++++----- packages/web/src/content/docs/docs/config.mdx | 10 +++++++-- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/bun.lock b/bun.lock index 4425429f..64c02b67 100644 --- a/bun.lock +++ b/bun.lock @@ -47,6 +47,7 @@ "hono": "catalog:", "hono-openapi": "0.4.8", "isomorphic-git": "1.32.1", + "jsonc-parser": "3.3.1", "open": "10.1.2", "remeda": "catalog:", "tree-sitter": "0.22.4", diff --git a/packages/opencode/package.json b/packages/opencode/package.json index cc31e83b..c8c502ed 100644 --- a/packages/opencode/package.json +++ b/packages/opencode/package.json @@ -45,6 +45,7 @@ "hono": "catalog:", "hono-openapi": "0.4.8", "isomorphic-git": "1.32.1", + "jsonc-parser": "3.3.1", "open": "10.1.2", "remeda": "catalog:", "turndown": "7.2.0", diff --git a/packages/opencode/src/cli/error.ts b/packages/opencode/src/cli/error.ts index 261206a1..77643001 100644 --- a/packages/opencode/src/cli/error.ts +++ b/packages/opencode/src/cli/error.ts @@ -5,7 +5,11 @@ import { UI } from "./ui" export function FormatError(input: unknown) { if (MCP.Failed.isInstance(input)) return `MCP server "${input.data.name}" failed. Note, opencode does not support MCP authentication yet.` - if (Config.JsonError.isInstance(input)) return `Config file at ${input.data.path} is not valid JSON` + if (Config.JsonError.isInstance(input)) { + return ( + `Config file at ${input.data.path} is not valid JSON(C)` + (input.data.message ? `: ${input.data.message}` : "") + ) + } if (Config.InvalidError.isInstance(input)) return [ `Config file at ${input.data.path} is invalid`, diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index ce3ae28a..0a9304c3 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -12,6 +12,7 @@ import { NamedError } from "../util/error" import matter from "gray-matter" import { Flag } from "../flag/flag" import { Auth } from "../auth" +import { type ParseError as JsoncParseError, parse as parseJsonc, printParseErrorCode } from "jsonc-parser" export namespace Config { const log = Log.create({ service: "config" }) @@ -371,11 +372,20 @@ export namespace Config { } } - let data: any - try { - data = JSON.parse(text) - } catch (err) { - throw new JsonError({ path: configPath }, { cause: err as Error }) + const errors: JsoncParseError[] = [] + const data = parseJsonc(text, errors, { allowTrailingComma: true }) + if (errors.length) { + throw new JsonError({ + path: configPath, + message: errors + .map((e) => { + const lines = text.substring(0, e.offset).split("\n") + const line = lines.length + const column = lines[lines.length - 1].length + 1 + return `${printParseErrorCode(e.error)} at line ${line}, column ${column}` + }) + .join("; "), + }) } const parsed = Info.safeParse(data) @@ -392,6 +402,7 @@ export namespace Config { "ConfigJsonError", z.object({ path: z.string(), + message: z.string().optional(), }), ) diff --git a/packages/web/src/content/docs/docs/config.mdx b/packages/web/src/content/docs/docs/config.mdx index abd05c33..01a16537 100644 --- a/packages/web/src/content/docs/docs/config.mdx +++ b/packages/web/src/content/docs/docs/config.mdx @@ -5,9 +5,14 @@ description: Using the opencode JSON config. You can configure opencode using a JSON config file. -```json title="opencode.json" +## Format + +opencode supports both JSON and JSONC (JSON with Comments) formats. You can use comments in your configuration files: + +```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", + // Theme configuration "theme": "opencode", "model": "anthropic/claude-sonnet-4-20250514", "autoupdate": true @@ -199,7 +204,7 @@ about rules here](/docs/rules). You can configure specialized agents for specific tasks through the `agent` option. -```json title="opencode.json" +```jsonc title="opencode.jsonc" { "$schema": "https://opencode.ai/config.json", "agent": { @@ -208,6 +213,7 @@ You can configure specialized agents for specific tasks through the `agent` opti "model": "anthropic/claude-sonnet-4-20250514", "prompt": "You are a code reviewer. Focus on security, performance, and maintainability.", "tools": { + // Disable file modification tools for review-only agent "write": false, "edit": false }