diff --git a/AGENTS.md b/AGENTS.md index d71e9235a4d..3ff62660676 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -203,6 +203,8 @@ We regularly merge upstream changes from opencode. To minimize merge conflicts a 4. **Avoid restructuring upstream code** - Don't refactor or reorganize code that comes from opencode unless absolutely necessary. +5. **Mirror new config keys to the cloud schema** - When adding a `kilocode_change` key to `Config.Info` in `packages/opencode/src/config/config.ts`, also add the matching JSON Schema entry in `apps/web/src/app/config.json/extras.ts` in the [cloud repo](https://github.com/Kilo-Org/cloud). See [CLI Config Schema](packages/kilo-docs/pages/contributing/architecture/config-schema.md) for the step-by-step. + The goal is to keep our diff from upstream as small as possible, making regular merges straightforward and reducing the risk of conflicts. ### Kilocode Change Markers diff --git a/packages/kilo-docs/lib/nav/contributing.ts b/packages/kilo-docs/lib/nav/contributing.ts index 34fb344f30f..74e75c5ede6 100644 --- a/packages/kilo-docs/lib/nav/contributing.ts +++ b/packages/kilo-docs/lib/nav/contributing.ts @@ -38,6 +38,10 @@ export const ContributingNav: NavSection[] = [ href: "/contributing/architecture/benchmarking", children: "Benchmarking", }, + { + href: "/contributing/architecture/config-schema", + children: "CLI Config Schema", + }, { href: "/contributing/architecture/enterprise-mcp-controls", children: "Enterprise MCP Controls", diff --git a/packages/kilo-docs/pages/contributing/architecture/config-schema.md b/packages/kilo-docs/pages/contributing/architecture/config-schema.md new file mode 100644 index 00000000000..c4cba931c05 --- /dev/null +++ b/packages/kilo-docs/pages/contributing/architecture/config-schema.md @@ -0,0 +1,33 @@ +--- +title: "CLI Config Schema" +description: "How the Kilo CLI config JSON Schema is served at app.kilo.ai/config.json" +--- + +# CLI Config Schema + +The JSON Schema referenced by `"$schema": "https://app.kilo.ai/config.json"` in `kilo.json` files is served by the cloud repo. It is a runtime overlay of the upstream opencode schema with Kilo-specific additions on top. + +## Flow + +1. Client fetches `https://app.kilo.ai/config.json`. +2. Cloud route `apps/web/src/app/config.json/route.ts` fetches `https://opencode.ai/config.json`, runs `merge()` on it, and returns the result. +3. `merge()` overlays three sections from `apps/web/src/app/config.json/extras.ts`: + - `top` — top-level keys like `commit_message`, `remote_control`, nullable `model` / `small_model` + - `agents` — Kilo primary agents (`ask`, `debug`, `orchestrator`) + - `experimental` — `codebase_search`, `openTelemetry` + +## Adding a new Kilo-only config key + +The source of truth is the zod schema in `packages/opencode/src/config/config.ts`. The cloud overlay must match it. + +1. Add the zod field with a `kilocode_change` marker in `config.ts`. +2. Generate the JSON Schema shape: `bun --bun packages/opencode/script/schema.ts /tmp/kilo.json`, then `jq '.properties.' /tmp/kilo.json`. +3. Paste the shape into the correct bucket in `apps/web/src/app/config.json/extras.ts` in the [cloud repo](https://github.com/Kilo-Org/cloud). + - Top-level → `top`; under `experimental` → `experimental`; new primary agent → `agents`; anywhere else → add a new bucket and extend `merge()` in `route.ts`. +4. Add an assertion in `apps/web/src/tests/cli-config-schema.test.ts`. + +If step 3 is skipped, users with `$schema: https://app.kilo.ai/config.json` will see "unknown property" warnings for the new key. + +## Caching + +The cloud route caches the upstream fetch for 1 hour (`next: { revalidate: 3600 }`) and emits `s-maxage=3600, stale-while-revalidate=3600`, so the response is served from the Cloudflare + Vercel edge cache for all but one request per hour per region. diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index e1d8d191018..33a011eb346 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -1033,10 +1033,15 @@ export namespace Config { .boolean() .optional() .describe("@deprecated Use 'share' field instead. Share newly created sessions automatically"), - remote_control: z // kilocode_change + // kilocode_change start + // NOTE: Any new kilocode_change key added to Config.Info must also be mirrored in + // apps/web/src/app/config.json/extras.ts in the cloud repo, otherwise + // $schema: https://app.kilo.ai/config.json will not recognize it. + remote_control: z .boolean() .optional() .describe("Enable remote control of sessions via Kilo Cloud. Equivalent to running /remote on startup."), + // kilocode_change end autoupdate: z .union([z.boolean(), z.literal("notify")]) .optional()