Selaa lähdekoodia

feat(cli): add debug config command (#40895)

Dax 1 viikko sitten
vanhempi
sitoutus
939da6a5e7
71 muutettua tiedostoa jossa 6989 lisäystä ja 1039 poistoa
  1. 4 1
      packages/cli/src/commands/commands.ts
  2. 19 0
      packages/cli/src/commands/handlers/debug/config.ts
  3. 1 0
      packages/cli/src/index.ts
  4. 83 0
      packages/cli/test/debug-config.test.ts
  5. 2 0
      packages/client/script/build.ts
  6. 12 0
      packages/client/src/effect/api/api.ts
  7. 10 0
      packages/client/src/effect/generated/client.ts
  8. 2 0
      packages/client/src/effect/index.ts
  9. 1 0
      packages/client/src/promise/api.ts
  10. 16 0
      packages/client/src/promise/generated/client.ts
  11. 182 0
      packages/client/src/promise/generated/types.ts
  12. 1 0
      packages/client/src/promise/index.ts
  13. 2 0
      packages/client/test/contract-identity.test.ts
  14. 29 0
      packages/client/test/promise.test.ts
  15. 21 147
      packages/core/src/config.ts
  16. 7 6
      packages/core/src/config/plugin/agent.ts
  17. 4 3
      packages/core/src/config/plugin/command.ts
  18. 2 1
      packages/core/src/config/plugin/policy.ts
  19. 3 2
      packages/core/src/config/plugin/provider.ts
  20. 3 2
      packages/core/src/config/plugin/reference.ts
  21. 2 1
      packages/core/src/filesystem/location-watcher.ts
  22. 1 1
      packages/core/src/mcp/client.ts
  23. 3 2
      packages/core/src/mcp/index.ts
  24. 1 1
      packages/core/src/mcp/oauth.ts
  25. 7 7
      packages/core/src/plugin/supervisor.ts
  26. 3 2
      packages/core/src/session/compaction.ts
  27. 1 1
      packages/core/src/v1/config/config.ts
  28. 10 9
      packages/core/test/config/agent.test.ts
  29. 6 6
      packages/core/test/config/command.test.ts
  30. 51 19
      packages/core/test/config/config.test.ts
  31. 1 1
      packages/core/test/config/model.test.ts
  32. 5 5
      packages/core/test/config/policy.test.ts
  33. 11 10
      packages/core/test/config/provider.test.ts
  34. 4 4
      packages/core/test/config/reload.test.ts
  35. 6 5
      packages/core/test/config/skill.test.ts
  36. 2 2
      packages/core/test/config/warming.test.ts
  37. 4 3
      packages/core/test/formatter.test.ts
  38. 4 3
      packages/core/test/mcp.test.ts
  39. 2 1
      packages/core/test/pty/pty-session.test.ts
  40. 6 5
      packages/core/test/session-runner.test.ts
  41. 8 7
      packages/core/test/tool-read.test.ts
  42. 2045 249
      packages/protocol/openapi.json
  43. 3 0
      packages/protocol/src/api.ts
  44. 1 0
      packages/protocol/src/client.ts
  45. 22 0
      packages/protocol/src/groups/config.ts
  46. 136 0
      packages/schema/src/config.ts
  47. 5 5
      packages/schema/src/config/agent.ts
  48. 2 2
      packages/schema/src/config/command.ts
  49. 2 2
      packages/schema/src/config/compaction.ts
  50. 3 3
      packages/schema/src/config/experimental.ts
  51. 1 1
      packages/schema/src/config/formatter.ts
  52. 1 1
      packages/schema/src/config/lsp.ts
  53. 2 4
      packages/schema/src/config/mcp.ts
  54. 2 2
      packages/schema/src/config/media.ts
  55. 3 3
      packages/schema/src/config/model.ts
  56. 1 1
      packages/schema/src/config/plugin.ts
  57. 1 1
      packages/schema/src/config/policy.ts
  58. 3 3
      packages/schema/src/config/provider.ts
  59. 1 1
      packages/schema/src/config/reference.ts
  60. 2 2
      packages/schema/src/config/tool-output.ts
  61. 1 1
      packages/schema/src/config/warming.ts
  62. 1 1
      packages/schema/src/config/watcher.ts
  63. 2 2
      packages/schema/src/config/websearch.ts
  64. 42 0
      packages/schema/test/config.test.ts
  65. 1 0
      packages/sdk-next/src/index.ts
  66. 3 0
      packages/sdk-next/test/contract-identity.test.ts
  67. 2 0
      packages/server/src/handlers.ts
  68. 7 0
      packages/server/src/handlers/config.ts
  69. 62 0
      packages/server/test/config.test.ts
  70. 2045 249
      packages/www/openapi.json
  71. 2045 249
      packages/www/public/openapi.json

+ 4 - 1
packages/cli/src/commands/commands.ts

@@ -68,7 +68,10 @@ export const Commands = Spec.make(typeof OPENCODE_CLI_NAME === "string" ? OPENCO
     }),
     Spec.make("debug", {
       description: "Debugging and troubleshooting tools",
-      commands: [Spec.make("agents", { description: "List all agents" })],
+      commands: [
+        Spec.make("agents", { description: "List all agents" }),
+        Spec.make("config", { description: "Show resolved configuration" }),
+      ],
     }),
     Spec.make("console", {
       description: "Manage OpenCode Console access",

+ 19 - 0
packages/cli/src/commands/handlers/debug/config.ts

@@ -0,0 +1,19 @@
+import { EOL } from "os"
+import { Effect } from "effect"
+import { OpenCode } from "@opencode-ai/client"
+import { Service } from "@opencode-ai/client/effect/service"
+import { Commands } from "../../commands"
+import { Runtime } from "../../../framework/runtime"
+import { ServiceConfig } from "../../../services/service-config"
+
+export default Runtime.handler(
+  Commands.commands.debug.commands.config,
+  Effect.fn("cli.debug.config")(function* () {
+    const options = yield* ServiceConfig.options()
+    const found = yield* Service.discover(options)
+    const endpoint = found ?? (yield* Service.ensure(options))
+    const client = OpenCode.make({ baseUrl: endpoint.url, headers: Service.headers(endpoint) })
+    const entries = yield* Effect.promise(() => client.config.get({ location: { directory: process.cwd() } }))
+    process.stdout.write(JSON.stringify(entries, null, 2) + EOL)
+  }),
+)

+ 1 - 0
packages/cli/src/index.ts

@@ -22,6 +22,7 @@ const Handlers = Runtime.handlers(Commands, {
   },
   debug: {
     agents: () => import("./commands/handlers/debug/agents"),
+    config: () => import("./commands/handlers/debug/config"),
   },
   console: {
     login: () => import("./commands/handlers/console/login"),

+ 83 - 0
packages/cli/test/debug-config.test.ts

@@ -0,0 +1,83 @@
+import { describe, expect, test } from "bun:test"
+import fs from "node:fs/promises"
+import os from "node:os"
+import path from "node:path"
+import { OPENCODE_VERSION } from "../src/version"
+
+describe("debug config command", () => {
+  test("is included in troubleshooting help", async () => {
+    const [debug, config] = await Promise.all([cli(["debug", "--help"]), cli(["debug", "config", "--help"])])
+
+    expect(debug.exitCode).toBe(0)
+    expect(debug.stdout).toContain("config")
+    expect(debug.stdout).toContain("Show resolved configuration")
+    expect(config.exitCode).toBe(0)
+    expect(config.stdout).toContain("opencode debug config [flags]")
+  })
+
+  test("prints config entries from the invoking directory without reordering permissions", async () => {
+    const root = await fs.mkdtemp(path.join(os.tmpdir(), "opencode-debug-config-"))
+    const project = path.join(import.meta.dir, "..")
+    const registration = path.join(root, "state", "opencode", "service-local.json")
+    const entries = [
+      {
+        type: "document",
+        path: path.join(project, "opencode.json"),
+        info: {
+          permissions: [
+            { action: "shell", resource: "*", effect: "ask" },
+            { action: "shell", resource: "git status", effect: "allow" },
+          ],
+        },
+      },
+      { type: "file", path: path.join(project, "opencode.json") },
+    ]
+    let requested: URL | undefined
+    const authorization: Array<string | null> = []
+    const server = Bun.serve({
+      port: 0,
+      fetch(request) {
+        const url = new URL(request.url)
+        if (url.pathname === "/api/health") {
+          return Response.json({ healthy: true, version: OPENCODE_VERSION, pid: process.pid })
+        }
+        requested = url
+        authorization.push(request.headers.get("authorization"))
+        return Response.json(entries)
+      },
+    })
+
+    try {
+      await fs.mkdir(path.dirname(registration), { recursive: true })
+      await fs.writeFile(
+        registration,
+        JSON.stringify({ version: OPENCODE_VERSION, url: server.url.toString(), pid: process.pid, password: "secret" }),
+      )
+      const result = await cli(["debug", "config"], project, { XDG_STATE_HOME: path.join(root, "state") })
+
+      expect({ exitCode: result.exitCode, stderr: result.stderr }).toEqual({ exitCode: 0, stderr: "" })
+      expect(JSON.parse(result.stdout)).toEqual(entries)
+      expect(requested?.pathname).toBe("/api/config")
+      expect(requested?.searchParams.get("location[directory]")).toBe(project)
+      expect(authorization).toEqual([`Basic ${btoa("opencode:secret")}`])
+    } finally {
+      server.stop(true)
+      await fs.rm(root, { recursive: true, force: true })
+    }
+  })
+})
+
+async function cli(args: string[], cwd = path.join(import.meta.dir, ".."), env?: Record<string, string>) {
+  const child = Bun.spawn([process.execPath, "run", path.join(import.meta.dir, "../src/index.ts"), ...args], {
+    cwd,
+    env: { ...process.env, ...env },
+    stdout: "pipe",
+    stderr: "pipe",
+  })
+  const [stdout, stderr, exitCode] = await Promise.all([
+    new Response(child.stdout).text(),
+    new Response(child.stderr).text(),
+    child.exited,
+  ])
+  return { stdout, stderr, exitCode }
+}

+ 2 - 0
packages/client/script/build.ts

@@ -8,6 +8,7 @@ import {
 } from "@opencode-ai/protocol/client"
 import { Agent } from "@opencode-ai/schema/agent"
 import { Command } from "@opencode-ai/schema/command"
+import { Config } from "@opencode-ai/schema/config"
 import { Credential } from "@opencode-ai/schema/credential"
 import { Event } from "@opencode-ai/schema/event"
 import { EventLog } from "@opencode-ai/schema/event-log"
@@ -48,6 +49,7 @@ const effectContract = compile(ClientApi, { groupNames, omitEndpoints: effectOmi
 const effectTypeReferences = [
   ...namespaceTypes("Agent", "@opencode-ai/schema/agent", Agent),
   ...namespaceTypes("Command", "@opencode-ai/schema/command", Command),
+  ...namespaceTypes("Config", "@opencode-ai/schema/config", Config),
   ...namespaceTypes("Credential", "@opencode-ai/schema/credential", Credential),
   ...namespaceTypes("Event", "@opencode-ai/schema/event", Event),
   ...namespaceTypes("EventLog", "@opencode-ai/schema/event-log", EventLog),

+ 12 - 0
packages/client/src/effect/api/api.ts

@@ -38,6 +38,7 @@ import type { ProjectCopy } from "@opencode-ai/schema/project-copy"
 import type { Vcs } from "@opencode-ai/schema/vcs"
 import type { FileDiff } from "@opencode-ai/schema/file-diff"
 import type { WebSearch } from "@opencode-ai/schema/websearch"
+import type { Config } from "@opencode-ai/schema/config"
 
 export type Endpoint0_0Output = { readonly healthy: true; readonly version: string; readonly pid: number }
 export type HealthGetOperation<E = never> = () => Effect.Effect<Endpoint0_0Output, E>
@@ -1595,6 +1596,16 @@ export interface WebsearchApi<E = never> {
   readonly query: WebsearchQueryOperation<E>
 }
 
+export type Endpoint29_0Input = {
+  readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
+}
+export type Endpoint29_0Output = ReadonlyArray<Config.Entry>
+export type ConfigGetOperation<E = never> = (input?: Endpoint29_0Input) => Effect.Effect<Endpoint29_0Output, E>
+
+export interface ConfigApi<E = never> {
+  readonly get: ConfigGetOperation<E>
+}
+
 export interface AppApi<E = never> {
   readonly health: HealthApi<E>
   readonly server: ServerApi<E>
@@ -1625,4 +1636,5 @@ export interface AppApi<E = never> {
   readonly debug: DebugApi<E>
   readonly migration: MigrationApi<E>
   readonly websearch: WebsearchApi<E>
+  readonly config: ConfigApi<E>
 }

+ 10 - 0
packages/client/src/effect/generated/client.ts

@@ -220,6 +220,8 @@ import type {
   Endpoint28_0Output,
   Endpoint28_1Input,
   Endpoint28_1Output,
+  Endpoint29_0Input,
+  Endpoint29_0Output,
 } from "../api/api.js"
 import { ClientError } from "./client-error"
 
@@ -1241,6 +1243,13 @@ const adaptGroup28 = (raw: RawClient["server.websearch"]) => ({
   query: Endpoint28_1(raw),
 })
 
+const Endpoint29_0 = (raw: RawClient["server.config"]) => (input?: Endpoint29_0Input) =>
+  preserveEffect<Endpoint29_0Output>()(
+    raw["config.get"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)),
+  )
+
+const adaptGroup29 = (raw: RawClient["server.config"]) => ({ get: Endpoint29_0(raw) })
+
 const adaptClient = (raw: RawClient) => ({
   health: adaptGroup0(raw["server.health"]),
   server: adaptGroup1(raw["server.server"]),
@@ -1271,6 +1280,7 @@ const adaptClient = (raw: RawClient) => ({
   debug: adaptGroup26(raw["server.debug"]),
   migration: adaptGroup27(raw["server.migration"]),
   websearch: adaptGroup28(raw["server.websearch"]),
+  config: adaptGroup29(raw["server.config"]),
 })
 
 export const make = (options?: { readonly baseUrl?: URL | string }) =>

+ 2 - 0
packages/client/src/effect/index.ts

@@ -8,6 +8,7 @@ export type {
   AppApi,
   CatalogApi,
   CommandApi,
+  ConfigApi,
   EventApi,
   IntegrationApi,
   ModelApi,
@@ -20,6 +21,7 @@ export type {
 } from "./api.js"
 export { Agent } from "@opencode-ai/schema/agent"
 export { Command } from "@opencode-ai/schema/command"
+export { Config } from "@opencode-ai/schema/config"
 export { Credential } from "@opencode-ai/schema/credential"
 export { Event } from "@opencode-ai/schema/event"
 export { EventLog } from "@opencode-ai/schema/event-log"

+ 1 - 0
packages/client/src/promise/api.ts

@@ -2,6 +2,7 @@ type Client = ReturnType<typeof import("./generated/client.js").make>
 
 export type AgentApi = Client["agent"]
 export type CommandApi = Client["command"]
+export type ConfigApi = Client["config"]
 export type EventApi = Client["event"]
 export type IntegrationApi = Client["integration"]
 export type ModelApi = Client["model"]

+ 16 - 0
packages/client/src/promise/generated/client.ts

@@ -216,6 +216,8 @@ import type {
   WebsearchProvidersOutput,
   WebsearchQueryInput,
   WebsearchQueryOutput,
+  ConfigGetInput,
+  ConfigGetOutput,
 } from "./types"
 import { ClientError } from "./client-error"
 
@@ -1811,6 +1813,20 @@ export function make(options: ClientOptions) {
           requestOptions,
         ),
     },
+    config: {
+      get: (input?: ConfigGetInput, requestOptions?: RequestOptions) =>
+        request<ConfigGetOutput>(
+          {
+            method: "GET",
+            path: `/api/config`,
+            query: { location: input?.["location"] },
+            successStatus: 200,
+            declaredStatuses: [401, 400],
+            empty: false,
+          },
+          requestOptions,
+        ),
+    },
   }
 }
 

+ 182 - 0
packages/client/src/promise/generated/types.ts

@@ -1698,6 +1698,180 @@ export type AgentInfo = {
   permissions: PermissionRuleset
 }
 
+export type ConfigEntry =
+  | {
+      type: "document"
+      path?: string | null
+      info: {
+        $schema?: string | null
+        shell?: string | null
+        model?: string | { providerID: string; model: string; variant?: string | null } | null
+        default_agent?: string | null
+        autoupdate?: boolean | "notify" | null
+        share?: "manual" | "auto" | "disabled" | null
+        enterprise?: { url?: string | null } | null
+        username?: string | null
+        permissions?: PermissionRuleset | null
+        agents?: {
+          [x: string]: {
+            model?: string | { providerID: string; model: string; variant?: string | null } | null
+            request?: { headers?: { [x: string]: string } | null; body?: { [x: string]: JsonValue } | null } | null
+            system?: string | null
+            description?: string | null
+            mode?: "subagent" | "primary" | "all" | null
+            hidden?: boolean | null
+            color?: string | null
+            steps?: number | null
+            disabled?: boolean | null
+            permissions?: PermissionRuleset | null
+          }
+        } | null
+        snapshots?: boolean | null
+        watcher?: { ignore?: Array<string> | null } | null
+        formatter?:
+          | boolean
+          | {
+              [x: string]: {
+                disabled?: boolean | null
+                command?: Array<string> | null
+                environment?: { [x: string]: string } | null
+                extensions?: Array<string> | null
+              }
+            }
+          | null
+        lsp?:
+          | boolean
+          | {
+              [x: string]:
+                | { disabled: true }
+                | {
+                    command: Array<string>
+                    extensions?: Array<string> | null
+                    disabled?: boolean | null
+                    env?: { [x: string]: string } | null
+                    initialization?: { [x: string]: JsonValue } | null
+                  }
+            }
+          | null
+        media?: {
+          image?: {
+            auto_resize?: boolean | null
+            max_width?: number | null
+            max_height?: number | null
+            max_base64_bytes?: number | null
+          } | null
+        } | null
+        tool_output?: { max_lines?: number | null; max_bytes?: number | null } | null
+        mcp?: {
+          timeout?: { startup?: number | null; catalog?: number | null; execution?: number | null } | null
+          servers?: {
+            [x: string]:
+              | {
+                  type: "local"
+                  command: Array<string>
+                  cwd?: string | null
+                  environment?: { [x: string]: string } | null
+                  disabled?: boolean | null
+                  codemode?: boolean | null
+                  timeout?: { startup?: number | null; catalog?: number | null; execution?: number | null } | null
+                }
+              | {
+                  type: "remote"
+                  url: string
+                  headers?: { [x: string]: string } | null
+                  oauth?:
+                    | {
+                        client_id?: string | null
+                        client_secret?: string | null
+                        scope?: string | null
+                        callback_port?: number | null
+                        redirect_uri?: string | null
+                      }
+                    | false
+                    | null
+                  disabled?: boolean | null
+                  codemode?: boolean | null
+                  timeout?: { startup?: number | null; catalog?: number | null; execution?: number | null } | null
+                }
+          } | null
+        } | null
+        compaction?: { auto?: boolean | null; keep?: { tokens?: number | null } | null; buffer?: number | null } | null
+        skills?: Array<string> | null
+        commands?: {
+          [x: string]: {
+            template: string
+            description?: string | null
+            agent?: string | null
+            model?: string | { providerID: string; model: string; variant?: string | null } | null
+            subtask?: boolean | null
+          }
+        } | null
+        instructions?: Array<string> | null
+        references?: {
+          [x: string]:
+            | string
+            | { repository: string; branch?: string | null; description?: string | null; hidden?: boolean | null }
+            | { path: string; description?: string | null; hidden?: boolean | null }
+        } | null
+        websearch?: { provider: string } | null
+        plugins?: Array<string | { package: string; options?: { [x: string]: JsonValue } | null }> | null
+        warming?: boolean | { prompt?: string | null; interval?: string | null; duration?: string | null } | null
+        providers?: {
+          [x: string]: {
+            name?: string | null
+            env?: Array<string> | null
+            package?: string | null
+            settings?: { [x: string]: JsonValue } | null
+            headers?: { [x: string]: string } | null
+            body?: { [x: string]: JsonValue } | null
+            models?: {
+              [x: string]: {
+                modelID?: string | null
+                family?: string | null
+                name?: string | null
+                compatibility?: ModelCompatibility | null
+                package?: string | null
+                settings?: { [x: string]: JsonValue } | null
+                headers?: { [x: string]: string } | null
+                body?: { [x: string]: JsonValue } | null
+                capabilities?: ModelCapabilities | null
+                variants?: Array<{
+                  id: string
+                  settings?: { [x: string]: JsonValue } | null
+                  headers?: { [x: string]: string } | null
+                  body?: { [x: string]: JsonValue } | null
+                }> | null
+                cost?:
+                  | {
+                      tier?: { type: "context"; size: number } | null
+                      input: MoneyUSDPerMillionTokens
+                      output: MoneyUSDPerMillionTokens
+                      cache?: { read?: MoneyUSDPerMillionTokens | null; write?: MoneyUSDPerMillionTokens | null } | null
+                    }
+                  | Array<{
+                      tier?: { type: "context"; size: number } | null
+                      input: MoneyUSDPerMillionTokens
+                      output: MoneyUSDPerMillionTokens
+                      cache?: { read?: MoneyUSDPerMillionTokens | null; write?: MoneyUSDPerMillionTokens | null } | null
+                    }>
+                  | null
+                disabled?: boolean | null
+                limit?: { context?: number | null; input?: number | null; output?: number | null } | null
+              }
+            } | null
+          }
+        } | null
+        experimental?: {
+          subagent_depth?: number | null
+          policies?: Array<{ action: "provider.use"; resource: string; effect: "allow" | "deny" }> | null
+        } | null
+      }
+    }
+  | { type: "directory"; path: string }
+  | { type: "file"; path: string }
+  | { type: "agents"; path: string }
+  | { type: "claude"; path: string }
+
 export type SessionsResponse = { data: Array<SessionInfo>; cursor: { previous?: string | null; next?: string | null } }
 
 export type SessionPendingUser = {
@@ -4593,3 +4767,11 @@ export type WebsearchQueryOutput = {
   location: { directory: string; workspaceID?: string; project: { id: string; directory: string; canonical: string } }
   data: { providerID: string; results: Array<WebSearchResult> }
 }
+
+export type ConfigGetInput = {
+  readonly location?: {
+    readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
+  }["location"]
+}
+
+export type ConfigGetOutput = Array<ConfigEntry>

+ 1 - 0
packages/client/src/promise/index.ts

@@ -3,6 +3,7 @@ export type {
   AgentApi,
   CatalogApi,
   CommandApi,
+  ConfigApi,
   EventApi,
   IntegrationApi,
   ModelApi,

+ 2 - 0
packages/client/test/contract-identity.test.ts

@@ -1,6 +1,7 @@
 import { expect, test } from "bun:test"
 import { Schema } from "effect"
 import { Agent } from "@opencode-ai/schema/agent"
+import { Config } from "@opencode-ai/schema/config"
 import { Model } from "@opencode-ai/schema/model"
 import { Prompt } from "@opencode-ai/schema/prompt"
 import { Session } from "@opencode-ai/schema/session"
@@ -10,6 +11,7 @@ const Client = await import("../src/effect")
 
 test("effect entrypoint exposes canonical Schema contracts", () => {
   expect(Client.Agent).toBe(Agent)
+  expect(Client.Config).toBe(Config)
   expect(Client.Model).toBe(Model)
   expect(Client.Session).toBe(Session)
 })

+ 29 - 0
packages/client/test/promise.test.ts

@@ -33,6 +33,7 @@ test("exposes every standard HTTP API group", () => {
     "vcs",
     "debug",
     "websearch",
+    "config",
   ])
   expect(Object.keys(client.debug)).toEqual(["location"])
   expect(Object.keys(client.debug.location)).toEqual(["list", "evict"])
@@ -50,6 +51,34 @@ test("exposes every standard HTTP API group", () => {
   expect(Object.keys(client.project)).toEqual(["list", "current", "directories"])
 })
 
+test("config.get returns ordered config entries for a location", async () => {
+  let request: Request | undefined
+  const entries = [
+    {
+      type: "document" as const,
+      path: "/tmp/project/opencode.json",
+      info: {
+        permissions: [
+          { action: "shell", resource: "*", effect: "ask" as const },
+          { action: "shell", resource: "git status", effect: "allow" as const },
+        ],
+      },
+    },
+    { type: "file" as const, path: "/tmp/project/opencode.json" },
+  ]
+  const client = OpenCode.make({
+    baseUrl: "http://localhost:3000",
+    fetch: async (input) => {
+      request = input instanceof Request ? input : new Request(input)
+      return Response.json(entries)
+    },
+  })
+
+  expect(await client.config.get({ location: { directory: "/tmp/project" } })).toEqual(entries)
+  expect(request?.method).toBe("GET")
+  expect(request?.url).toBe("http://localhost:3000/api/config?location%5Bdirectory%5D=%2Ftmp%2Fproject")
+})
+
 test("websearch.query uses the public HTTP contract", async () => {
   let request: Request | undefined
   const client = OpenCode.make({

+ 21 - 147
packages/core/src/config.ts

@@ -5,8 +5,16 @@ import path from "path"
 import { isDeepStrictEqual } from "node:util"
 import { type ParseError, parse } from "jsonc-parser"
 import { Context, Effect, Layer, Option, PubSub, Ref, Schema, Semaphore, Stream } from "effect"
-import { Permission } from "@opencode-ai/schema/permission"
-import { Config as ConfigSchema } from "@opencode-ai/schema/config"
+import {
+  AgentsDirectory,
+  ClaudeDirectory,
+  Directory,
+  Document,
+  File,
+  Info,
+  type Entry,
+  Event,
+} from "@opencode-ai/schema/config"
 import { Integration } from "@opencode-ai/schema/integration"
 import { Credential } from "./credential"
 import { Bus } from "./bus"
@@ -15,141 +23,11 @@ import { FSUtil } from "@opencode-ai/util/fs-util"
 import { Global } from "@opencode-ai/util/global"
 import { Location } from "./location"
 import { AbsolutePath } from "./schema"
-import { ConfigAgent } from "./config/agent"
-import { ConfigMedia } from "./config/media"
-import { ConfigCompaction } from "./config/compaction"
-import { ConfigCommand } from "./config/command"
-import { ConfigExperimental } from "./config/experimental"
-import { ConfigFormatter } from "./config/formatter"
-import { ConfigLSP } from "./config/lsp"
-import { ConfigMCP } from "./config/mcp"
-import { ConfigModel } from "./config/model"
-import { ConfigPlugin } from "./config/plugin"
-import { ConfigProvider } from "./config/provider"
-import { ConfigReference } from "./config/reference"
-import { ConfigWebSearch } from "./config/websearch"
-import { ConfigToolOutput } from "./config/tool-output"
 import { ConfigVariable } from "./config/variable"
-import { ConfigWatcher } from "./config/watcher"
-import { ConfigWarming } from "./config/warming"
 import { ConfigV1 } from "./v1/config/config"
 import { ConfigMigrateV1 } from "./v1/config/migrate"
 import { WellKnown } from "./wellknown"
 
-export class Info extends Schema.Class<Info>("Config.Info")({
-  $schema: Schema.optional(Schema.String).annotate({
-    description: "JSON schema reference for configuration validation",
-  }),
-  shell: Schema.String.pipe(Schema.optional).annotate({
-    description: "Default shell to use for terminal and shell tool execution",
-  }),
-  model: ConfigModel.Selection.pipe(Schema.optional).annotate({
-    description: "Default model to use when no session or agent model is selected",
-  }),
-  default_agent: Schema.String.pipe(Schema.optional).annotate({
-    description: "Default primary agent to use when no session agent is selected",
-  }),
-  autoupdate: Schema.Union([Schema.Boolean, Schema.Literal("notify")])
-    .pipe(Schema.optional)
-    .annotate({
-      description: "Automatically update or notify when a new version is available",
-    }),
-  share: Schema.Literals(["manual", "auto", "disabled"]).pipe(Schema.optional).annotate({
-    description: "Control whether sessions may be shared manually, automatically, or not at all",
-  }),
-  enterprise: Schema.Struct({
-    url: Schema.String.pipe(Schema.optional),
-  })
-    .pipe(Schema.optional)
-    .annotate({
-      description: "Enterprise sharing service configuration",
-    }),
-  username: Schema.String.pipe(Schema.optional).annotate({
-    description: "Username displayed in conversations and used for telemetry identity",
-  }),
-  permissions: Permission.Ruleset.pipe(Schema.optional).annotate({
-    description: "Ordered tool permission rules applied to agent tool use",
-  }),
-  agents: Schema.Record(Schema.String, ConfigAgent.Info).pipe(Schema.optional).annotate({
-    description: "Named built-in agent overrides and custom agent definitions",
-  }),
-  snapshots: Schema.Boolean.pipe(Schema.optional).annotate({
-    description: "Enable snapshots used for undo and revert behavior",
-  }),
-  watcher: ConfigWatcher.Info.pipe(Schema.optional).annotate({
-    description: "Filesystem watcher configuration",
-  }),
-  formatter: ConfigFormatter.Info.pipe(Schema.optional).annotate({
-    description: "Enable built-in formatters or configure formatter overrides",
-  }),
-  lsp: ConfigLSP.Info.pipe(Schema.optional).annotate({
-    description: "Enable built-in language servers or configure server overrides",
-  }),
-  media: ConfigMedia.Info.pipe(Schema.optional).annotate({
-    description: "Media processing configuration",
-  }),
-  tool_output: ConfigToolOutput.Info.pipe(Schema.optional).annotate({
-    description: "Tool output truncation thresholds",
-  }),
-  mcp: ConfigMCP.Info.pipe(Schema.optional).annotate({
-    description: "MCP server configuration",
-  }),
-  compaction: ConfigCompaction.Info.pipe(Schema.optional).annotate({
-    description: "Conversation compaction behavior",
-  }),
-  skills: Schema.String.pipe(Schema.Array, Schema.optional).annotate({
-    description: "Additional paths or URLs to discover skills from",
-  }),
-  commands: Schema.Record(Schema.String, ConfigCommand.Info).pipe(Schema.optional).annotate({
-    description: "Named slash command definitions",
-  }),
-  instructions: Schema.String.pipe(Schema.Array, Schema.optional).annotate({
-    description: "Additional paths or URLs supplying ambient instructions",
-  }),
-  references: ConfigReference.Info.pipe(Schema.optional).annotate({
-    description: "Named local directories or Git repositories available as external context",
-  }),
-  websearch: ConfigWebSearch.Info.pipe(Schema.optional).annotate({
-    description: "Web search provider selection",
-  }),
-  plugins: ConfigPlugin.Plugins.pipe(Schema.optional).annotate({
-    description: "Ordered plugin enablement directives and external package declarations",
-  }),
-  warming: ConfigWarming.Warming.pipe(Schema.optional).annotate({
-    description: "Keep recently active sessions warm with transient model requests (default: false)",
-  }),
-  providers: Schema.Record(Schema.String, ConfigProvider.Info).pipe(Schema.optional),
-  experimental: ConfigExperimental.Info.pipe(Schema.optional),
-}) {}
-
-export class Document extends Schema.Class<Document>("Config.Document")({
-  type: Schema.Literal("document"),
-  path: Schema.String.pipe(Schema.optional),
-  info: Info,
-}) {}
-
-export class Directory extends Schema.Class<Directory>("Config.Directory")({
-  type: Schema.Literal("directory"),
-  path: AbsolutePath,
-}) {}
-
-export class File extends Schema.Class<File>("Config.File")({
-  type: Schema.Literal("file"),
-  path: AbsolutePath,
-}) {}
-
-export class AgentsDirectory extends Schema.Class<AgentsDirectory>("Config.AgentsDirectory")({
-  type: Schema.Literal("agents"),
-  path: AbsolutePath,
-}) {}
-
-export class ClaudeDirectory extends Schema.Class<ClaudeDirectory>("Config.ClaudeDirectory")({
-  type: Schema.Literal("claude"),
-  path: AbsolutePath,
-}) {}
-
-export type Entry = Document | Directory | File | AgentsDirectory | ClaudeDirectory
-
 export function latest<K extends keyof Info>(entries: readonly Entry[], key: K): Info[K] | undefined {
   return entries
     .filter((entry): entry is Document => entry.type === "document")
@@ -296,21 +174,17 @@ export const layer = (options?: Options) => Layer.effect(
 
       // We load certain files from a few other folders in the ecosystem
       const claude = [
-        ...((yield* fs.isDir(globalClaudeDirectory))
-          ? [new ClaudeDirectory({ type: "claude", path: globalClaudeDirectory })]
-          : []),
-        ...discovered
-          .filter((item) => path.basename(item) === ".claude")
-          .map((directory) => new ClaudeDirectory({ type: "claude", path: AbsolutePath.make(directory) })),
-      ]
+        ...new Set([
+          ...((yield* fs.isDir(globalClaudeDirectory)) ? [globalClaudeDirectory] : []),
+          ...discovered.filter((item) => path.basename(item) === ".claude"),
+        ]),
+      ].map((directory) => new ClaudeDirectory({ type: "claude", path: AbsolutePath.make(directory) }))
       const agents = [
-        ...((yield* fs.isDir(globalAgentsDirectory))
-          ? [new AgentsDirectory({ type: "agents", path: globalAgentsDirectory })]
-          : []),
-        ...discovered
-          .filter((item) => path.basename(item) === ".agents")
-          .map((directory) => new AgentsDirectory({ type: "agents", path: AbsolutePath.make(directory) })),
-      ]
+        ...new Set([
+          ...((yield* fs.isDir(globalAgentsDirectory)) ? [globalAgentsDirectory] : []),
+          ...discovered.filter((item) => path.basename(item) === ".agents"),
+        ]),
+      ].map((directory) => new AgentsDirectory({ type: "agents", path: AbsolutePath.make(directory) }))
 
       const directories = [
         globalDirectory,
@@ -408,7 +282,7 @@ export const layer = (options?: Options) => Layer.effect(
           if (isDeepStrictEqual(configs, next)) return
           configs = next
           yield* reconcile(next)
-          yield* bus.publish(ConfigSchema.Event.Updated, {})
+          yield* bus.publish(Event.Updated, {})
         }),
       ),
     )

+ 7 - 6
packages/core/src/config/plugin/agent.ts

@@ -1,11 +1,12 @@
 export * as ConfigAgentPlugin from "./agent"
 
 import { define } from "@opencode-ai/plugin/effect/plugin"
+import { Document, Info, type Entry } from "@opencode-ai/schema/config"
+import { ConfigAgent } from "@opencode-ai/schema/config/agent"
 import path from "path"
 import { Effect, Option, Schema, Stream } from "effect"
 import { Agent } from "../../agent"
 import { Config } from "../../config"
-import { ConfigAgent } from "../agent"
 import { ConfigMarkdown } from "../markdown"
 import { FSUtil } from "@opencode-ai/util/fs-util"
 import { ConfigAgentV1 } from "../../v1/config/agent"
@@ -24,7 +25,7 @@ const legacySources = [
 const sourceDirectories = ["agent", "agents", "mode", "modes"] as const
 const decodeAgent = Schema.decodeUnknownOption(ConfigAgent.Info)
 const decodeLegacyAgent = Schema.decodeUnknownOption(ConfigAgentV1.Info)
-const decodeConfig = Schema.decodeUnknownOption(Config.Info)
+const decodeConfig = Schema.decodeUnknownOption(Info)
 type PathAction =
   | LocationMutation.ExternalDirectoryAuthorization["action"]
   | typeof ReadTool.name
@@ -63,13 +64,13 @@ export const Plugin = define({
             ),
           ).pipe(
             Effect.map((documents) =>
-              documents.filter((document): document is Config.Document => document !== undefined),
+              documents.filter((document): document is Document => document !== undefined),
             ),
           )
         })
       }).pipe(Effect.map((documents) => documents.flat()))
     })
-    const loaded = { documents: [] as Config.Document[] }
+    const loaded = { documents: [] as Document[] }
     const reload = load().pipe(
       Effect.tap((documents) => Effect.sync(() => (loaded.documents = documents))),
       Effect.andThen(ctx.agent.reload()),
@@ -139,7 +140,7 @@ export const Plugin = define({
 
 // Matches anything at or under <root>/{agent,agents,mode,modes}. No file-suffix
 // check: directory-level events such as renames carry no per-file paths.
-function isAgentSource(entries: Config.Entry[], file: string) {
+function isAgentSource(entries: Entry[], file: string) {
   return entries.some(
     (entry) =>
       entry.type === "directory" &&
@@ -208,5 +209,5 @@ function decode(file: { directory: string; filepath: string; primary: boolean },
     }),
   )
   if (!info) return
-  return new Config.Document({ type: "document", path: file.filepath, info })
+  return new Document({ type: "document", path: file.filepath, info })
 }

+ 4 - 3
packages/core/src/config/plugin/command.ts

@@ -1,12 +1,13 @@
 export * as ConfigCommandPlugin from "./command"
 
 import { define } from "@opencode-ai/plugin/effect/plugin"
+import { Info, type Entry } from "@opencode-ai/schema/config"
+import { ConfigCommand } from "@opencode-ai/schema/config/command"
 import path from "path"
 import { Effect, Option, Schema, Stream } from "effect"
 import { Command } from "../../command"
 import { Config } from "../../config"
 import { FSUtil } from "@opencode-ai/util/fs-util"
-import { ConfigCommand } from "../command"
 import { ConfigMarkdown } from "../markdown"
 
 const decodeCommand = Schema.decodeUnknownOption(ConfigCommand.Info)
@@ -27,7 +28,7 @@ export const Plugin = define({
         )
       }).pipe(Effect.map((documents) => documents.flat()))
     })
-    const loaded = { documents: [] as { commands: Config.Info["commands"] }[] }
+    const loaded = { documents: [] as { commands: Info["commands"] }[] }
     const reload = load().pipe(
       Effect.tap((documents) => Effect.sync(() => (loaded.documents = documents))),
       Effect.andThen(ctx.command.reload()),
@@ -75,7 +76,7 @@ const sourceDirectories = ["command", "commands"] as const
 
 // Matches anything at or under <root>/{command,commands}. No file-suffix check:
 // directory-level events such as renames carry no per-file paths.
-function isCommandSource(entries: Config.Entry[], file: string) {
+function isCommandSource(entries: Entry[], file: string) {
   return entries.some(
     (entry) =>
       entry.type === "directory" &&

+ 2 - 1
packages/core/src/config/plugin/policy.ts

@@ -1,6 +1,7 @@
 export * as ConfigPolicyPlugin from "./policy"
 
 import { define } from "@opencode-ai/plugin/effect/plugin"
+import { Document } from "@opencode-ai/schema/config"
 import { Effect, Stream } from "effect"
 import { Config } from "../../config"
 import { Wildcard } from "../../util/wildcard"
@@ -13,7 +14,7 @@ export const Plugin = define({
     yield* ctx.catalog.transform((catalog) => {
       // User-global policy takes priority over policy authored by a repository.
       const policies = loaded.entries
-        .filter((entry): entry is Config.Document => entry.type === "document")
+        .filter((entry): entry is Document => entry.type === "document")
         .toReversed()
         .flatMap((entry) => entry.info.experimental?.policies ?? [])
       for (const record of catalog.provider.list()) {

+ 3 - 2
packages/core/src/config/plugin/provider.ts

@@ -1,6 +1,7 @@
 export * as ConfigProviderPlugin from "./provider"
 
 import { define } from "@opencode-ai/plugin/effect/plugin"
+import { Document, type Entry } from "@opencode-ai/schema/config"
 import { Money } from "@opencode-ai/schema/money"
 import { Effect, Stream } from "effect"
 import { Config } from "../../config"
@@ -107,8 +108,8 @@ export const Plugin = define({
   }),
 })
 
-function configuredProviders(entries: readonly Config.Entry[]) {
+function configuredProviders(entries: readonly Entry[]) {
   return entries
-    .filter((entry): entry is Config.Document => entry.type === "document")
+    .filter((entry): entry is Document => entry.type === "document")
     .flatMap((file) => Object.entries(file.info.providers ?? {}))
 }

+ 3 - 2
packages/core/src/config/plugin/reference.ts

@@ -1,10 +1,11 @@
 export * as ConfigReferencePlugin from "./reference"
 
 import { define } from "@opencode-ai/plugin/effect/plugin"
+import { Document } from "@opencode-ai/schema/config"
+import { ConfigReference } from "@opencode-ai/schema/config/reference"
 import path from "path"
 import { Effect, Stream } from "effect"
 import { Config } from "../../config"
-import { ConfigReference } from "../reference"
 import { Reference } from "../../reference"
 import { AbsolutePath } from "../../schema"
 import { Global } from "@opencode-ai/util/global"
@@ -19,7 +20,7 @@ export const Plugin = define({
     const loaded = { entries: yield* config.entries() }
     yield* ctx.reference.transform((draft) => {
       const entries = new Map<string, Reference.Source>()
-      for (const doc of loaded.entries.filter((entry): entry is Config.Document => entry.type === "document")) {
+      for (const doc of loaded.entries.filter((entry): entry is Document => entry.type === "document")) {
         const directory = doc.path ? path.dirname(doc.path) : location.directory
         for (const [name, entry] of Object.entries(doc.info.references ?? {})) {
           if (!validAlias(name)) continue

+ 2 - 1
packages/core/src/filesystem/location-watcher.ts

@@ -3,6 +3,7 @@ export * as LocationWatcher from "./location-watcher"
 import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
 import { Context, Effect, Layer, Stream } from "effect"
 import { FileSystem } from "@opencode-ai/schema/filesystem"
+import { Document } from "@opencode-ai/schema/config"
 import path from "path"
 import { Config } from "../config"
 import { Bus } from "../bus"
@@ -41,7 +42,7 @@ const layer = Layer.effect(
 
     yield* Effect.gen(function* () {
       const config = (yield* configService.entries())
-        .filter((entry): entry is Config.Document => entry.type === "document")
+        .filter((entry): entry is Document => entry.type === "document")
         .flatMap((item) => item.info.watcher?.ignore ?? [])
       const home = Protected.isHome(location.directory)
 

+ 1 - 1
packages/core/src/mcp/client.ts

@@ -29,7 +29,7 @@ import {
   ToolSchema,
 } from "@modelcontextprotocol/sdk/types.js"
 import { Cause, Effect, Exit, Schema } from "effect"
-import { ConfigMCP } from "../config/mcp"
+import { ConfigMCP } from "@opencode-ai/schema/config/mcp"
 
 const DEFAULT_STARTUP_TIMEOUT = 30_000
 const DEFAULT_CATALOG_TIMEOUT = 30_000

+ 3 - 2
packages/core/src/mcp/index.ts

@@ -3,11 +3,12 @@ export * as MCP from "./index"
 import { Mcp } from "@opencode-ai/schema/mcp"
 import { McpEvent } from "@opencode-ai/schema/mcp-event"
 import { Command } from "@opencode-ai/schema/command"
+import { Document } from "@opencode-ai/schema/config"
+import { ConfigMCP } from "@opencode-ai/schema/config/mcp"
 import { createHash } from "node:crypto"
 import { Cause, Context, Deferred, Effect, Exit, FiberSet, Layer, Schema, Scope, Stream } from "effect"
 import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
 import { Config } from "../config"
-import { ConfigMCP } from "../config/mcp"
 import { Credential } from "../credential"
 import { Bus } from "../bus"
 import { Form } from "../form"
@@ -178,7 +179,7 @@ export const layer = (options?: Options) => Layer.effect(
     const fork = yield* FiberSet.makeRuntime<never, void, never>()
     yield* Effect.addFinalizer((exit) => Scope.close(root, exit))
 
-    const documents = (yield* config.entries()).filter((entry): entry is Config.Document => entry.type === "document")
+    const documents = (yield* config.entries()).filter((entry): entry is Document => entry.type === "document")
     // Global MCP timeout defaults, later config files overriding earlier ones.
     const timeout = Object.assign(
       {},

+ 1 - 1
packages/core/src/mcp/oauth.ts

@@ -5,7 +5,7 @@ import type { OAuthClientInformationMixed, OAuthTokens } from "@modelcontextprot
 import { createServer } from "node:http"
 import { Deferred, Effect } from "effect"
 import { Credential } from "@opencode-ai/schema/credential"
-import { ConfigMCP } from "../config/mcp"
+import { ConfigMCP } from "@opencode-ai/schema/config/mcp"
 import { OauthCallbackPage } from "../oauth/page"
 import type { Integration } from "../integration"
 

+ 7 - 7
packages/core/src/plugin/supervisor.ts

@@ -1,7 +1,8 @@
 export * as PluginSupervisor from "./supervisor"
 
 import type { Plugin as PluginDefinition } from "@opencode-ai/plugin/effect/plugin"
-import { Event } from "@opencode-ai/schema/config"
+import { Directory, Document, Event, type Entry } from "@opencode-ai/schema/config"
+import { ConfigPlugin } from "@opencode-ai/schema/config/plugin"
 import { Context, Deferred, Effect, Layer, Option, PubSub, Schema, Stream } from "effect"
 import path from "path"
 import { fileURLToPath, pathToFileURL } from "url"
@@ -9,7 +10,6 @@ import { Agent } from "../agent"
 import { Catalog } from "../catalog"
 import { Command } from "../command"
 import { Config } from "../config"
-import { ConfigPlugin } from "../config/plugin"
 import { Credential } from "../credential"
 import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
 import { httpClient } from "@opencode-ai/util/effect/app-node-platform"
@@ -83,15 +83,15 @@ function parse(input: ConfigPlugin.Plugin): Operation {
   return { type: "remove", target: input.slice(1) }
 }
 
-const scan = Effect.fn("PluginSupervisor.scan")(function* (entries: readonly Config.Entry[]) {
+const scan = Effect.fn("PluginSupervisor.scan")(function* (entries: readonly Entry[]) {
   const fs = yield* FSUtil.Service
   const location = yield* Location.Service
   const discovered = yield* Effect.forEach(
-    entries.filter((entry): entry is Config.Directory => entry.type === "directory"),
+    entries.filter((entry): entry is Directory => entry.type === "directory"),
     (entry) => discoverDirectory(fs, entry.path),
   ).pipe(Effect.map((items) => items.flat()))
   const configured = entries
-    .filter((entry): entry is Config.Document => entry.type === "document")
+    .filter((entry): entry is Document => entry.type === "document")
     .flatMap((entry) =>
       (entry.info.plugins ?? []).map(parse).map((operation) => {
         if (operation.type === "remove") return operation
@@ -208,7 +208,7 @@ function discoverDirectory(fs: FSUtil.Interface, directory: string) {
 
 const sourceDirectories = ["plugin", "plugins"] as const
 
-function isPluginSource(entries: readonly Config.Entry[], file: string) {
+function isPluginSource(entries: readonly Entry[], file: string) {
   return entries.some(
     (entry) =>
       entry.type === "directory" &&
@@ -243,7 +243,7 @@ const layer = Layer.effect(
     const configuredChanges = yield* PubSub.unbounded<void>()
     const watched = new Set<string>()
     const watchConfiguredSources = Effect.fn("PluginSupervisor.watchConfiguredSources")(function* (
-      entries: readonly Config.Entry[],
+      entries: readonly Entry[],
       operations: readonly Operation[],
     ) {
       for (const operation of operations) {

+ 3 - 2
packages/core/src/session/compaction.ts

@@ -2,6 +2,7 @@ export * as SessionCompaction from "./compaction"
 
 import { LLM, LLMClient, AIError, LLMEvent, Message, type LLMRequest, type LanguageModel } from "@opencode-ai/ai"
 import { SessionError } from "@opencode-ai/schema/session-error"
+import { Document, type Entry } from "@opencode-ai/schema/config"
 import { Context, Effect, Layer, Stream } from "effect"
 import { Config } from "../config"
 import { Bus } from "../bus"
@@ -148,9 +149,9 @@ const serialize = (message: SessionMessage.Info) => {
   return ""
 }
 
-const settings = (documents: readonly Config.Entry[]) => {
+const settings = (documents: readonly Entry[]) => {
   const configured = documents
-    .filter((entry): entry is Config.Document => entry.type === "document")
+    .filter((entry): entry is Document => entry.type === "document")
     .flatMap((entry) => (entry.info.compaction ? [entry.info.compaction] : []))
   return {
     auto: configured.findLast((value) => value.auto !== undefined)?.auto ?? true,

+ 1 - 1
packages/core/src/v1/config/config.ts

@@ -1,8 +1,8 @@
 export * as ConfigV1 from "./config"
 
 import { Schema } from "effect"
+import { ConfigReference } from "@opencode-ai/schema/config/reference"
 import { NonNegativeInt, PositiveInt, type DeepMutable } from "../../schema"
-import { ConfigReference } from "../../config/reference"
 import { ConfigAgentV1 } from "./agent"
 import { ConfigAttachmentV1 } from "./attachment"
 import { ConfigCommandV1 } from "./command"

+ 10 - 9
packages/core/test/config/agent.test.ts

@@ -5,6 +5,7 @@ import { Effect, Fiber, Schema, Stream } from "effect"
 import { Agent } from "@opencode-ai/core/agent"
 import { Bus } from "@opencode-ai/core/bus"
 import { Config } from "@opencode-ai/core/config"
+import { Directory, Document, Info } from "@opencode-ai/schema/config"
 import { ConfigAgentPlugin } from "@opencode-ai/core/config/plugin/agent"
 import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
 import { LayerNode } from "@opencode-ai/util/effect/layer-node"
@@ -19,7 +20,7 @@ import { testEffect } from "../lib/effect"
 import { agentHost, host } from "../plugin/host"
 
 const it = testEffect(AppNodeBuilder.build(LayerNode.group([Agent.node, Bus.node, FSUtil.node, Global.node])))
-const decode = Schema.decodeUnknownSync(Config.Info)
+const decode = Schema.decodeUnknownSync(Info)
 const defaultPermissions = (global: Global.Interface): Permission.Ruleset => [
   ...Agent.Info.default(Agent.ID.make("test")).permissions,
   { action: "external_directory", resource: path.join(global.data, "shell", "*", "*"), effect: "allow" },
@@ -71,7 +72,7 @@ describe("ConfigAgentPlugin.Plugin", () => {
       )
 
       const entries = [
-        new Config.Document({
+        new Document({
           type: "document",
           info: decode({
             permissions: [{ action: "bash", resource: "*", effect: "ask" }],
@@ -92,7 +93,7 @@ describe("ConfigAgentPlugin.Plugin", () => {
             },
           }),
         }),
-        new Config.Document({
+        new Document({
           type: "document",
           info: decode({
             permissions: [{ action: "read", resource: "*", effect: "allow" }],
@@ -153,7 +154,7 @@ describe("ConfigAgentPlugin.Plugin", () => {
     Effect.gen(function* () {
       const agents = yield* Agent.Service
       const entries = [
-        new Config.Document({
+        new Document({
           type: "document",
           info: decode({
             agents: {
@@ -173,7 +174,7 @@ describe("ConfigAgentPlugin.Plugin", () => {
             },
           }),
         }),
-        new Config.Document({
+        new Document({
           type: "document",
           info: decode({
             agents: {
@@ -218,7 +219,7 @@ describe("ConfigAgentPlugin.Plugin", () => {
       yield* agents.transform((editor) => editor.update(build, () => {}))
 
       const entries = [
-        new Config.Document({
+        new Document({
           type: "document",
           info: decode({ agents: { build: { disabled: true } } }),
         }),
@@ -276,7 +277,7 @@ Use native v2 fields.`,
           const agents = yield* Agent.Service
           const global = yield* Global.Service
           const entries = [
-            new Config.Document({
+            new Document({
               type: "document",
               info: decode({ agents: { reviewer: { description: "JSON description" } } }),
             }),
@@ -425,7 +426,7 @@ Use native v2 fields.`,
 })
 
 function directoryEntry(directory: string) {
-  return new Config.Directory({ type: "directory", path: AbsolutePath.make(directory) })
+  return new Directory({ type: "directory", path: AbsolutePath.make(directory) })
 }
 
 function sourceCases() {
@@ -522,7 +523,7 @@ function loadHomePermissions(home: string) {
     const build = Agent.ID.make("build")
     yield* agents.transform((editor) => editor.update(build, () => {}))
     const entries = [
-      new Config.Document({
+      new Document({
         type: "document",
         info: decode(
           ConfigMigrateV1.migrate({

+ 6 - 6
packages/core/test/config/command.test.ts

@@ -3,7 +3,7 @@ import path from "path"
 import { describe, expect } from "bun:test"
 import { Deferred, Effect, Fiber, Layer, Option, PubSub, Schema, Stream } from "effect"
 import { advance, drain } from "../lib/clock"
-import { Config as ConfigSchema } from "@opencode-ai/schema/config"
+import { Directory, Document, Event, Info } from "@opencode-ai/schema/config"
 import { Command } from "@opencode-ai/core/command"
 import { Agent } from "@opencode-ai/core/agent"
 import { Config } from "@opencode-ai/core/config"
@@ -35,7 +35,7 @@ const it = testEffect(
     [Location.node, testLocationLayer],
   ]),
 )
-const decode = Schema.decodeUnknownSync(Config.Info)
+const decode = Schema.decodeUnknownSync(Info)
 
 describe("ConfigCommandPlugin.Plugin", () => {
   it.live("loads inline and file-based commands in config order", () =>
@@ -63,7 +63,7 @@ Review files`,
 
           const command = yield* Command.Service
           const bus = yield* Bus.Service
-          const update = yield* bus.publish(ConfigSchema.Event.Updated, {})
+          const update = yield* bus.publish(Event.Updated, {})
           const updates = yield* PubSub.unbounded<typeof update>()
           yield* ConfigCommandPlugin.Plugin.effect(
             host({
@@ -77,11 +77,11 @@ Review files`,
           ).pipe(
             Effect.provide(
               Config.testLayer([
-                new Config.Document({
+                new Document({
                   type: "document",
                   info: decode({ commands: { review: { template: "Inline review" } } }),
                 }),
-                new Config.Directory({ type: "directory", path: AbsolutePath.make(tmp.path) }),
+                new Directory({ type: "directory", path: AbsolutePath.make(tmp.path) }),
               ]),
             ),
           )
@@ -333,7 +333,7 @@ function watchReady(config: Config.Interface, directory: string) {
 }
 
 function directoryEntry(directory: string) {
-  return new Config.Directory({ type: "directory", path: AbsolutePath.make(directory) })
+  return new Directory({ type: "directory", path: AbsolutePath.make(directory) })
 }
 
 function sourceCases() {

+ 51 - 19
packages/core/test/config/config.test.ts

@@ -4,9 +4,9 @@ import { describe, expect } from "bun:test"
 import { Effect, Fiber, Layer, PubSub, Schema, Stream } from "effect"
 import { FastCheck } from "effect/testing"
 import { Config } from "@opencode-ai/core/config"
-import { ConfigModel } from "@opencode-ai/core/config/model"
-import { Config as ConfigSchema } from "@opencode-ai/schema/config"
-import { ConfigProvider } from "@opencode-ai/core/config/provider"
+import { AgentsDirectory, Directory, Document, Event, Info } from "@opencode-ai/schema/config"
+import { ConfigModel } from "@opencode-ai/schema/config/model"
+import { ConfigProvider } from "@opencode-ai/schema/config/provider"
 import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
 import { makeGlobalNode } from "@opencode-ai/util/effect/app-node"
 import { LayerNode } from "@opencode-ai/util/effect/layer-node"
@@ -161,7 +161,7 @@ describe("Config", () => {
             const bus = yield* Bus.Service
             const watcher = yield* Watcher.Test
             const changed = yield* bus
-              .subscribe(ConfigSchema.Event.Updated)
+              .subscribe(Event.Updated)
               .pipe(Stream.take(1), Stream.runCollect, Effect.forkScoped)
             yield* Effect.sleep("10 millis")
 
@@ -234,14 +234,14 @@ describe("Config", () => {
             yield* Effect.sleep("10 millis")
 
             const removed = yield* bus
-              .subscribe(ConfigSchema.Event.Updated)
+              .subscribe(Event.Updated)
               .pipe(Stream.take(1), Stream.runDrain, Effect.forkScoped({ startImmediately: true }))
             yield* Effect.promise(() => fs.rm(file))
             yield* Fiber.join(removed).pipe(Effect.timeout("5 seconds"))
             expect(Config.latest(yield* config.entries(), "shell")).toBeUndefined()
 
             const recreated = yield* bus
-              .subscribe(ConfigSchema.Event.Updated)
+              .subscribe(Event.Updated)
               .pipe(Stream.take(1), Stream.runDrain, Effect.forkScoped({ startImmediately: true }))
             yield* Effect.promise(() => fs.writeFile(file, JSON.stringify({ shell: "two" })))
             yield* Fiber.join(recreated).pipe(Effect.timeout("5 seconds"))
@@ -273,7 +273,7 @@ describe("Config", () => {
       const test = yield* Config.Test
       expect(yield* config.entries()).toEqual([])
 
-      const entry = new Config.Document({ type: "document", info: new Config.Info({}) })
+      const entry = new Document({ type: "document", info: new Info({}) })
       yield* test.setEntries([entry])
       expect(yield* config.entries()).toEqual([entry])
 
@@ -289,16 +289,16 @@ describe("Config", () => {
   it.effect("returns the latest defined scalar from priority-ordered documents", () =>
     Effect.sync(() => {
       const entries = [
-        new Config.Document({
+        new Document({
           type: "document",
-          info: new Config.Info({ model: selection("openrouter/openai/gpt-5") }),
+          info: new Info({ model: selection("openrouter/openai/gpt-5") }),
         }),
-        new Config.Directory({ type: "directory", path: AbsolutePath.make("/skills") }),
-        new Config.AgentsDirectory({ type: "agents", path: AbsolutePath.make("/agents") }),
-        new Config.Document({ type: "document", info: new Config.Info({}) }),
-        new Config.Document({
+        new Directory({ type: "directory", path: AbsolutePath.make("/skills") }),
+        new AgentsDirectory({ type: "agents", path: AbsolutePath.make("/agents") }),
+        new Document({ type: "document", info: new Info({}) }),
+        new Document({
           type: "document",
-          info: new Config.Info({ model: selection("openrouter/openai/gpt-5.5") }),
+          info: new Info({ model: selection("openrouter/openai/gpt-5.5") }),
         }),
       ]
 
@@ -372,7 +372,7 @@ describe("Config", () => {
             const bus = yield* Bus.Service
             expect(Config.latest(yield* config.entries(), "shell")).toBe("secret")
             const updated = yield* bus
-              .subscribe(ConfigSchema.Event.Updated)
+              .subscribe(Event.Updated)
               .pipe(Stream.take(1), Stream.runCollect, Effect.forkScoped)
             yield* Effect.yieldNow
             key = "next"
@@ -418,7 +418,7 @@ describe("Config", () => {
               Schema.encodeUnknownSync(Schema.UnknownFromJsonString)(info),
             ),
           )
-          Schema.decodeUnknownSync(Config.Info)(ConfigMigrateV1.migrate(parsed), { errors: "all" })
+          Schema.decodeUnknownSync(Info)(ConfigMigrateV1.migrate(parsed), { errors: "all" })
         }),
         { numRuns: 100 },
       )
@@ -661,13 +661,45 @@ describe("Config", () => {
           const entries = yield* config.entries()
 
           expect(entries).toEqual([
-            new Config.Directory({ type: "directory", path: AbsolutePath.make(path.join(tmp.path, "global")) }),
+            new Directory({ type: "directory", path: AbsolutePath.make(path.join(tmp.path, "global")) }),
           ])
         }).pipe(Effect.provide(testLayer(tmp.path))),
       ),
     ),
   )
 
+  it.live("deduplicates global ecosystem directories found during upward discovery", () =>
+    Effect.acquireRelease(
+      Effect.promise(() => tmpdir()),
+      (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
+    ).pipe(
+      Effect.flatMap((tmp) =>
+        Effect.gen(function* () {
+          const global = path.join(tmp.path, "global")
+          const home = path.join(global, "home")
+          const project = path.join(home, "project")
+          yield* Effect.promise(() =>
+            Promise.all([
+              fs.mkdir(path.join(home, ".claude"), { recursive: true }),
+              fs.mkdir(path.join(home, ".agents"), { recursive: true }),
+              fs.mkdir(project, { recursive: true }),
+            ]),
+          )
+          const entries = yield* Config.Service.use((config) => config.entries()).pipe(
+            Effect.provide(testLayer(project, global)),
+          )
+
+          expect(entries.filter((entry) => entry.type === "claude").map((entry) => entry.path)).toEqual([
+            AbsolutePath.make(path.join(home, ".claude")),
+          ])
+          expect(entries.filter((entry) => entry.type === "agents").map((entry) => entry.path)).toEqual([
+            AbsolutePath.make(path.join(home, ".agents")),
+          ])
+        }),
+      ),
+    ),
+  )
+
   it.live("does not watch ecosystem config roots", () =>
     Effect.acquireRelease(
       Effect.promise(() => tmpdir()),
@@ -729,7 +761,7 @@ describe("Config", () => {
             expect(documents).toHaveLength(2)
             expect(documents.map((document) => document.type)).toEqual(["document", "document"])
             expect(documents.map((document) => document.info.$schema)).toEqual(["base", "last"])
-            expect(documents[0]).toBeInstanceOf(Config.Document)
+            expect(documents[0]).toBeInstanceOf(Document)
             expect(documents[0]?.path).toBe(path.join(tmp.path, "opencode.json"))
             expect(documents[1]?.info.providers?.last).toBeInstanceOf(ConfigProvider.Info)
 
@@ -1177,7 +1209,7 @@ describe("Config", () => {
             const documents = (yield* config.entries()).filter((entry) => entry.type === "document")
 
             expect(documents).toHaveLength(1)
-            expect(documents[0]?.info).toBeInstanceOf(Config.Info)
+            expect(documents[0]?.info).toBeInstanceOf(Info)
             expect(documents[0]?.info.shell).toBe("/bin/zsh")
             expect(documents[0]?.info.default_agent).toBe("reviewer")
             expect(documents[0]?.info.snapshots).toBe(false)

+ 1 - 1
packages/core/test/config/model.test.ts

@@ -1,5 +1,5 @@
 import { describe, expect, test } from "bun:test"
-import { ConfigModel } from "@opencode-ai/core/config/model"
+import { ConfigModel } from "@opencode-ai/schema/config/model"
 import { Model } from "@opencode-ai/schema/model"
 import { Provider } from "@opencode-ai/schema/provider"
 import { Schema } from "effect"

+ 5 - 5
packages/core/test/config/policy.test.ts

@@ -1,5 +1,5 @@
 import { describe, expect } from "bun:test"
-import { Config as ConfigSchema } from "@opencode-ai/schema/config"
+import { Document, Event, Info, type Entry } from "@opencode-ai/schema/config"
 import { Catalog } from "@opencode-ai/core/catalog"
 import { Config } from "@opencode-ai/core/config"
 import { ConfigPolicyPlugin } from "@opencode-ai/core/config/plugin/policy"
@@ -12,10 +12,10 @@ import { testEffect } from "../lib/effect"
 import { PluginTestLayer } from "../plugin/fixture"
 
 const it = testEffect(PluginTestLayer)
-const decode = Schema.decodeUnknownSync(Config.Info)
+const decode = Schema.decodeUnknownSync(Info)
 
 const policies = (...items: { effect: "allow" | "deny"; resource: string }[]) =>
-  new Config.Document({
+  new Document({
     type: "document",
     info: decode({
       experimental: {
@@ -24,7 +24,7 @@ const policies = (...items: { effect: "allow" | "deny"; resource: string }[]) =>
     }),
   })
 
-const addPlugin = Effect.fn(function* (entries: Config.Entry[]) {
+const addPlugin = Effect.fn(function* (entries: Entry[]) {
   const plugin = yield* Plugin.Service
   const host = yield* PluginHost.make(plugin)
   yield* ConfigPolicyPlugin.Plugin.effect(host).pipe(Effect.provide(Config.testLayer(entries)))
@@ -78,7 +78,7 @@ describe("ConfigPolicyPlugin.Plugin", () => {
       expect(yield* catalog.provider.get(Provider.ID.openai)).toBeUndefined()
 
       yield* test.setEntries([policies({ effect: "allow", resource: "openai" })])
-      yield* bus.publish(ConfigSchema.Event.Updated, {})
+      yield* bus.publish(Event.Updated, {})
       yield* waitUntil(catalog.provider.get(Provider.ID.openai).pipe(Effect.map((provider) => provider !== undefined)))
     }).pipe(Effect.provide(Config.testLayer([policies({ effect: "deny", resource: "openai" })]))),
   )

+ 11 - 10
packages/core/test/config/provider.test.ts

@@ -1,5 +1,6 @@
 import { describe, expect } from "bun:test"
 import { Money } from "@opencode-ai/schema/money"
+import { Document, Info, type Entry } from "@opencode-ai/schema/config"
 import { Effect, Schema, Stream } from "effect"
 import { Catalog } from "@opencode-ai/core/catalog"
 import { Config } from "@opencode-ai/core/config"
@@ -14,7 +15,7 @@ import { PluginTestLayer } from "../plugin/fixture"
 
 const it = testEffect(PluginTestLayer)
 
-const addPlugin = Effect.fn(function* (entries: Config.Entry[]) {
+const addPlugin = Effect.fn(function* (entries: Entry[]) {
   const plugin = yield* Plugin.Service
   const host = yield* PluginHost.make(plugin)
   yield* ConfigProviderPlugin.Plugin.effect(host).pipe(Effect.provide(Config.testLayer(entries)))
@@ -46,7 +47,7 @@ function withEnv<A, E, R>(vars: Record<string, string | undefined>, effect: () =
   )
 }
 
-const decode = Schema.decodeUnknownSync(Config.Info)
+const decode = Schema.decodeUnknownSync(Info)
 
 describe("ConfigProviderPlugin.Plugin", () => {
   it.effect("defaults custom models to agent capabilities", () =>
@@ -55,7 +56,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
       const providerID = Provider.ID.make("custom")
       const modelID = Model.ID.make("chat")
       const entries = [
-        new Config.Document({
+        new Document({
           type: "document",
           info: decode({
             providers: {
@@ -90,7 +91,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
         })
       })
       const entries = [
-        new Config.Document({
+        new Document({
           type: "document",
           info: decode({
             providers: {
@@ -129,7 +130,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
       const providerID = Provider.ID.opencode
       const modelID = Model.ID.make("alpha-gpt-next")
       const entries = [
-        new Config.Document({
+        new Document({
           type: "document",
           info: decode({
             providers: {
@@ -178,7 +179,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
       const providerID = Provider.ID.opencode
       const modelID = Model.ID.make("alpha-gpt-next")
       const entries = [
-        new Config.Document({
+        new Document({
           type: "document",
           info: decode({
             providers: {
@@ -189,7 +190,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
             },
           }),
         }),
-        new Config.Document({
+        new Document({
           type: "document",
           info: decode({
             providers: {
@@ -223,7 +224,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
         const providerID = Provider.ID.make("custom")
         const modelID = Model.ID.make("chat")
         const entries = [
-          new Config.Document({
+          new Document({
             type: "document",
             info: decode({
               model: "custom/first",
@@ -255,7 +256,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
               },
             }),
           }),
-          new Config.Document({
+          new Document({
             type: "document",
             info: decode({
               model: "custom/default",
@@ -289,7 +290,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
               },
             }),
           }),
-          new Config.Document({
+          new Document({
             type: "document",
             info: decode({
               providers: {

+ 4 - 4
packages/core/test/config/reload.test.ts

@@ -1,6 +1,6 @@
 import path from "path"
 import { describe, expect } from "bun:test"
-import { Config as ConfigSchema } from "@opencode-ai/schema/config"
+import { Document, Event, Info } from "@opencode-ai/schema/config"
 import { Agent } from "@opencode-ai/core/agent"
 import { Catalog } from "@opencode-ai/core/catalog"
 import { Command } from "@opencode-ai/core/command"
@@ -22,7 +22,7 @@ import { testEffect } from "../lib/effect"
 import { PluginTestLayer } from "../plugin/fixture"
 
 const it = testEffect(PluginTestLayer)
-const decode = Schema.decodeUnknownSync(Config.Info)
+const decode = Schema.decodeUnknownSync(Info)
 const document = path.join(import.meta.dir, "opencode.json")
 
 describe("config plugin reloads", () => {
@@ -54,7 +54,7 @@ describe("config plugin reloads", () => {
 
       yield* test.setEntries([config("second")])
       yield* Effect.yieldNow
-      yield* bus.publish(ConfigSchema.Event.Updated, {})
+      yield* bus.publish(Event.Updated, {})
       yield* waitUntil(
         Effect.gen(function* () {
           return (
@@ -83,7 +83,7 @@ describe("config plugin reloads", () => {
 })
 
 function config(name: string) {
-  return new Config.Document({
+  return new Document({
     type: "document",
     path: document,
     info: decode({

+ 6 - 5
packages/core/test/config/skill.test.ts

@@ -2,6 +2,7 @@ import path from "path"
 import { describe, expect } from "bun:test"
 import { Effect, Layer, Schema, Stream } from "effect"
 import { Config } from "@opencode-ai/core/config"
+import { AgentsDirectory, ClaudeDirectory, Directory, Document, Info } from "@opencode-ai/schema/config"
 import { ConfigSkillPlugin } from "@opencode-ai/core/config/plugin/skill"
 import { Global } from "@opencode-ai/util/global"
 import { Location } from "@opencode-ai/core/location"
@@ -12,7 +13,7 @@ import { testEffect } from "../lib/effect"
 import { host } from "../plugin/host"
 
 const it = testEffect(Layer.empty)
-const decode = Schema.decodeUnknownSync(Config.Info)
+const decode = Schema.decodeUnknownSync(Info)
 
 describe("ConfigSkillPlugin.Plugin", () => {
   it.effect("registers configured skill directories and URLs", () =>
@@ -43,10 +44,10 @@ describe("ConfigSkillPlugin.Plugin", () => {
         Effect.provideService(Location.Service, Location.Service.of(location({ directory }))),
         Effect.provide(
           Config.testLayer([
-            new Config.ClaudeDirectory({ type: "claude", path: AbsolutePath.make("/repo/.claude") }),
-            new Config.AgentsDirectory({ type: "agents", path: AbsolutePath.make("/repo/.agents") }),
-            new Config.Directory({ type: "directory", path: AbsolutePath.make("/repo/.opencode") }),
-            new Config.Document({
+            new ClaudeDirectory({ type: "claude", path: AbsolutePath.make("/repo/.claude") }),
+            new AgentsDirectory({ type: "agents", path: AbsolutePath.make("/repo/.agents") }),
+            new Directory({ type: "directory", path: AbsolutePath.make("/repo/.opencode") }),
+            new Document({
               type: "document",
               info: decode({
                 skills: ["./skills", "~/shared-skills", "/opt/skills", "https://example.test/skills/"],

+ 2 - 2
packages/core/test/config/warming.test.ts

@@ -1,8 +1,8 @@
 import { describe, expect, test } from "bun:test"
 import { Duration, Schema } from "effect"
-import { Config } from "../../src/config"
+import { Info } from "@opencode-ai/schema/config"
 
-const decode = Schema.decodeUnknownSync(Config.Info)
+const decode = Schema.decodeUnknownSync(Info)
 
 describe("config warming", () => {
   test("accepts boolean enablement", () => {

+ 4 - 3
packages/core/test/formatter.test.ts

@@ -5,6 +5,7 @@ import { Effect, Layer, Schema, Stream } from "effect"
 import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
 import { AbsolutePath } from "@opencode-ai/core/schema"
 import { Npm } from "@opencode-ai/util/npm"
+import { Document, Info } from "@opencode-ai/schema/config"
 import { Config } from "../src/config"
 import { Formatter } from "../src/formatter"
 import { Location } from "../src/location"
@@ -13,16 +14,16 @@ import { tmpdir } from "./fixture/tmpdir"
 import { testEffect } from "./lib/effect"
 
 const it = testEffect(Layer.empty)
-type ConfigInput = typeof Config.Info.Encoded
+type ConfigInput = typeof Info.Encoded
 
 function formatterLayer(directory: string, configured?: ConfigInput["formatter"]) {
   const entries =
     configured === undefined
       ? []
       : [
-          new Config.Document({
+          new Document({
             type: "document",
-            info: Schema.decodeUnknownSync(Config.Info)({ formatter: configured }),
+            info: Schema.decodeUnknownSync(Info)({ formatter: configured }),
           }),
         ]
   return AppNodeBuilder.build(Formatter.node, [

+ 4 - 3
packages/core/test/mcp.test.ts

@@ -12,7 +12,8 @@ import {
   ListToolsRequestSchema,
   ReadResourceRequestSchema,
 } from "@modelcontextprotocol/sdk/types.js"
-import { ConfigMCP } from "@opencode-ai/core/config/mcp"
+import { Document, Info } from "@opencode-ai/schema/config"
+import { ConfigMCP } from "@opencode-ai/schema/config/mcp"
 import { Config } from "@opencode-ai/core/config"
 import { Credential } from "@opencode-ai/core/credential"
 import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
@@ -162,9 +163,9 @@ function resourceMcpLayer(
     Layer.provide(
       Layer.mergeAll(
         Config.testLayer([
-          new Config.Document({
+          new Document({
             type: "document",
-            info: new Config.Info({
+            info: new Info({
               mcp: new ConfigMCP.Info({
                 servers: {
                   resources:

+ 2 - 1
packages/core/test/pty/pty-session.test.ts

@@ -1,6 +1,7 @@
 import { describe, expect } from "bun:test"
 import { Cause, Deferred, Effect, Exit, Layer, Queue } from "effect"
 import { Config } from "@opencode-ai/core/config"
+import { Document, Info } from "@opencode-ai/schema/config"
 import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
 import { LayerNode } from "@opencode-ai/util/effect/layer-node"
 import { Bus } from "@opencode-ai/core/bus"
@@ -213,7 +214,7 @@ const configuredIt = testEffect(
         entries: () =>
           Effect.succeed(
             configuredShell
-              ? [new Config.Document({ type: "document", info: new Config.Info({ shell: configuredShell }) })]
+              ? [new Document({ type: "document", info: new Info({ shell: configuredShell }) })]
               : [],
           ),
       }),

+ 6 - 5
packages/core/test/session-runner.test.ts

@@ -49,9 +49,10 @@ import { SystemPromptPlugin } from "@opencode-ai/core/plugin/system-prompt"
 import { QuestionTool } from "@opencode-ai/core/tool/plugin/question"
 import { Agent } from "@opencode-ai/core/agent"
 import { Config } from "@opencode-ai/core/config"
-import { ConfigCompaction } from "@opencode-ai/core/config/compaction"
+import { Document, Info } from "@opencode-ai/schema/config"
+import { ConfigCompaction } from "@opencode-ai/schema/config/compaction"
 import { Tool } from "@opencode-ai/core/tool"
-import type { Info } from "@opencode-ai/schema/tool"
+import type { Info as ToolInfo } from "@opencode-ai/schema/tool"
 import {
   InstructionStateTable,
   SessionPendingTable,
@@ -228,7 +229,7 @@ const permission = Layer.succeed(
     list: () => Effect.die("unused"),
   }),
 )
-const transformTools = (registry: Tool.Interface, tools: Readonly<Record<string, Info>>, options?: Tool.Options) =>
+const transformTools = (registry: Tool.Interface, tools: Readonly<Record<string, ToolInfo>>, options?: Tool.Options) =>
   registry.transform((draft) =>
     Object.entries(tools).forEach(([name, tool]) => draft.add({ ...tool, name, options: options ?? tool.options })),
   )
@@ -334,9 +335,9 @@ const referenceInstructions = Layer.mock(ReferenceInstructions.Service, {
 })
 const mcpInstructions = Layer.mock(McpInstructions.Service, { load: () => Effect.succeed(Instructions.empty) })
 const config = Config.testLayer([
-  new Config.Document({
+  new Document({
     type: "document",
-    info: new Config.Info({
+    info: new Info({
       compaction: new ConfigCompaction.Info({
         buffer: 3_000,
         keep: new ConfigCompaction.Keep({ tokens: 1_000 }),

+ 8 - 7
packages/core/test/tool-read.test.ts

@@ -2,7 +2,8 @@ import { beforeEach, describe, expect } from "bun:test"
 import path from "path"
 import { Effect, Exit, Layer, PlatformError, Stream } from "effect"
 import { Config } from "@opencode-ai/core/config"
-import { ConfigMedia } from "@opencode-ai/core/config/media"
+import { Document, Info } from "@opencode-ai/schema/config"
+import { ConfigMedia } from "@opencode-ai/schema/config/media"
 import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
 import { LayerNode } from "@opencode-ai/util/effect/layer-node"
 import { FileSystem } from "@opencode-ai/core/filesystem"
@@ -429,9 +430,9 @@ describe("ReadTool", () => {
       }
       const configTest = yield* Config.Test
       yield* configTest.setEntries([
-        new Config.Document({
+        new Document({
           type: "document",
-          info: new Config.Info({
+          info: new Info({
             media: new ConfigMedia.Info({
               image: new ConfigMedia.Image({ auto_resize: false, max_width: 4 }),
             }),
@@ -472,9 +473,9 @@ describe("ReadTool", () => {
       }
       const configTest = yield* Config.Test
       yield* configTest.setEntries([
-        new Config.Document({
+        new Document({
           type: "document",
-          info: new Config.Info({
+          info: new Info({
             media: new ConfigMedia.Info({ image: new ConfigMedia.Image({ max_width: 4 }) }),
           }),
         }),
@@ -511,9 +512,9 @@ describe("ReadTool", () => {
       }
       const configTest = yield* Config.Test
       yield* configTest.setEntries([
-        new Config.Document({
+        new Document({
           type: "document",
-          info: new Config.Info({
+          info: new Info({
             media: new ConfigMedia.Info({
               image: new ConfigMedia.Image({ max_base64_bytes: 1 }),
             }),

+ 2045 - 249
packages/protocol/openapi.json

@@ -1025,14 +1025,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -1540,14 +1533,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -2912,14 +2898,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -3009,14 +2988,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -3586,14 +3558,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -3820,14 +3785,11 @@
               "application/json": {
                 "schema": {
                   "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/MessageNotFoundError"
-                    },
                     {
                       "$ref": "#/components/schemas/SessionNotFoundError"
                     },
                     {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
+                      "$ref": "#/components/schemas/MessageNotFoundError"
                     }
                   ]
                 }
@@ -3956,14 +3918,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -11771,39 +11726,101 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "type": "object",
-                  "properties": {
-                    "status": {
-                      "type": "string",
-                      "enum": [
-                        "required",
-                        "running",
-                        "completed"
-                      ]
+                  "anyOf": [
+                    {
+                      "type": "object",
+                      "properties": {
+                        "status": {
+                          "type": "string",
+                          "enum": [
+                            "required",
+                            "completed"
+                          ]
+                        }
+                      },
+                      "required": [
+                        "status"
+                      ],
+                      "additionalProperties": false
                     },
-                    "completed": {
-                      "type": "integer",
-                      "allOf": [
-                        {
-                          "minimum": 0
+                    {
+                      "type": "object",
+                      "properties": {
+                        "status": {
+                          "type": "string",
+                          "enum": [
+                            "running"
+                          ]
+                        },
+                        "progress": {
+                          "type": "object",
+                          "properties": {
+                            "label": {
+                              "type": "string"
+                            },
+                            "numerator": {
+                              "anyOf": [
+                                {
+                                  "type": "integer",
+                                  "allOf": [
+                                    {
+                                      "minimum": 0
+                                    }
+                                  ]
+                                },
+                                {
+                                  "type": "null"
+                                }
+                              ]
+                            },
+                            "denominator": {
+                              "anyOf": [
+                                {
+                                  "type": "integer",
+                                  "allOf": [
+                                    {
+                                      "minimum": 0
+                                    }
+                                  ]
+                                },
+                                {
+                                  "type": "null"
+                                }
+                              ]
+                            }
+                          },
+                          "required": [
+                            "label"
+                          ],
+                          "additionalProperties": false
                         }
-                      ]
+                      },
+                      "required": [
+                        "status",
+                        "progress"
+                      ],
+                      "additionalProperties": false
                     },
-                    "total": {
-                      "type": "integer",
-                      "allOf": [
-                        {
-                          "minimum": 0
+                    {
+                      "type": "object",
+                      "properties": {
+                        "status": {
+                          "type": "string",
+                          "enum": [
+                            "error"
+                          ]
+                        },
+                        "error": {
+                          "type": "string"
                         }
-                      ]
+                      },
+                      "required": [
+                        "status",
+                        "error"
+                      ],
+                      "additionalProperties": false
                     }
-                  },
-                  "required": [
-                    "status",
-                    "completed",
-                    "total"
-                  ],
-                  "additionalProperties": false
+                  ]
                 }
               }
             }
@@ -11831,60 +11848,6 @@
         },
         "description": "Return the progress of the V1 to V2 session history migration.",
         "summary": "Get V1 migration status"
-      },
-      "post": {
-        "tags": [
-          "migration"
-        ],
-        "operationId": "v2.experimental.migration.v1.run",
-        "parameters": [],
-        "security": [],
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "type": "object",
-                  "properties": {
-                    "status": {
-                      "type": "string",
-                      "enum": [
-                        "completed"
-                      ]
-                    }
-                  },
-                  "required": [
-                    "status"
-                  ],
-                  "additionalProperties": false
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "InvalidRequestError",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/InvalidRequestError"
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "UnauthorizedError",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/UnauthorizedError"
-                }
-              }
-            }
-          }
-        },
-        "description": "Run or resume the V1 to V2 session history migration and wait for completion.",
-        "summary": "Run V1 migration"
       }
     },
     "/api/websearch/provider": {
@@ -12134,6 +12097,94 @@
           "required": true
         }
       }
+    },
+    "/api/config": {
+      "get": {
+        "tags": [
+          "config"
+        ],
+        "operationId": "v2.config.get",
+        "parameters": [
+          {
+            "name": "location",
+            "in": "query",
+            "schema": {
+              "anyOf": [
+                {
+                  "type": "object",
+                  "properties": {
+                    "directory": {
+                      "anyOf": [
+                        {
+                          "type": "string"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    },
+                    "workspace": {
+                      "anyOf": [
+                        {
+                          "type": "string"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    }
+                  },
+                  "additionalProperties": false
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "required": false,
+            "style": "deepObject",
+            "explode": true
+          }
+        ],
+        "security": [],
+        "responses": {
+          "200": {
+            "description": "Success",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/Config.Entry"
+                  }
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "InvalidRequestError",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/InvalidRequestError"
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "UnauthorizedError",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UnauthorizedError"
+                }
+              }
+            }
+          }
+        },
+        "description": "Return configuration documents and discovery sources for the requested location, from lowest to highest priority.",
+        "summary": "Get configuration"
+      }
     }
   },
   "components": {
@@ -16014,7 +16065,10 @@
                     }
                   ]
                 }
-              }
+              },
+              "text": {
+                "type": "string"
+              }
             },
             "required": [
               "sessionID",
@@ -26457,120 +26511,1862 @@
           "results"
         ],
         "additionalProperties": false
-      }
-    },
-    "securitySchemes": {}
-  },
-  "security": [],
-  "tags": [
-    {
-      "name": "health"
-    },
-    {
-      "name": "server"
-    },
-    {
-      "name": "location"
-    },
-    {
-      "name": "agent"
-    },
-    {
-      "name": "plugin",
-      "description": "Experimental plugin routes."
-    },
-    {
-      "name": "session",
-      "description": "Experimental session routes."
-    },
-    {
-      "name": "session",
-      "description": "Experimental message routes."
-    },
-    {
-      "name": "model",
-      "description": "Experimental model routes."
-    },
-    {
-      "name": "generate",
-      "description": "Experimental one-shot generation routes."
-    },
-    {
-      "name": "provider",
-      "description": "Experimental provider routes."
-    },
-    {
-      "name": "integration",
-      "description": "Integration discovery and authentication routes."
-    },
-    {
-      "name": "mcp",
-      "description": "MCP server and resource routes."
-    },
-    {
-      "name": "credential"
-    },
-    {
-      "name": "project",
-      "description": "Location-scoped project routes."
-    },
-    {
-      "name": "form",
-      "description": "Session form routes."
-    },
-    {
-      "name": "permission",
-      "description": "Experimental permission routes."
-    },
-    {
-      "name": "filesystem",
-      "description": "Experimental location-scoped filesystem routes."
-    },
-    {
-      "name": "command",
-      "description": "Experimental command routes."
-    },
-    {
-      "name": "skill",
-      "description": "Experimental skill routes."
-    },
-    {
-      "name": "event",
-      "description": "Experimental event stream routes."
-    },
-    {
-      "name": "pty",
-      "description": "Experimental location-scoped PTY routes."
-    },
-    {
-      "name": "shell",
-      "description": "Experimental location-scoped shell command routes."
-    },
-    {
-      "name": "question",
-      "description": "Experimental session question routes."
-    },
-    {
-      "name": "reference",
-      "description": "Location-scoped project references."
-    },
-    {
-      "name": "projectCopy",
-      "description": "Project copy management routes."
-    },
-    {
-      "name": "vcs",
-      "description": "Location-scoped version control routes."
-    },
-    {
-      "name": "debug"
-    },
-    {
-      "name": "migration"
-    },
-    {
-      "name": "websearch",
-      "description": "Location-scoped web search routes."
+      },
+      "Config.ModelSelection": {
+        "anyOf": [
+          {
+            "type": "string",
+            "allOf": [
+              {
+                "pattern": "^[^/#]+\\/[^#]+(?:#[^#]+)?$"
+              }
+            ]
+          },
+          {
+            "type": "object",
+            "properties": {
+              "providerID": {
+                "type": "string",
+                "allOf": [
+                  {
+                    "pattern": "^[^/#]+$"
+                  }
+                ]
+              },
+              "model": {
+                "type": "string",
+                "allOf": [
+                  {
+                    "pattern": "^[^#]+$"
+                  }
+                ]
+              },
+              "variant": {
+                "anyOf": [
+                  {
+                    "type": "string",
+                    "allOf": [
+                      {
+                        "pattern": "^[^#]+$"
+                      }
+                    ]
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            },
+            "required": [
+              "providerID",
+              "model"
+            ],
+            "additionalProperties": false
+          }
+        ]
+      },
+      "Config.Provider.Request": {
+        "type": "object",
+        "properties": {
+          "headers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "body": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Agent": {
+        "type": "object",
+        "properties": {
+          "model": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ModelSelection"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "request": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Provider.Request"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "system": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "mode": {
+            "anyOf": [
+              {
+                "type": "string",
+                "enum": [
+                  "subagent",
+                  "primary",
+                  "all"
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "hidden": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "color": {
+            "anyOf": [
+              {
+                "type": "string",
+                "allOf": [
+                  {
+                    "pattern": "^#[0-9a-fA-F]{6}$"
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "steps": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "permissions": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Permission.Ruleset"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Watcher": {
+        "type": "object",
+        "properties": {
+          "ignore": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Formatter.Entry": {
+        "type": "object",
+        "properties": {
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "command": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "environment": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "extensions": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.LSP.Server": {
+        "type": "object",
+        "properties": {
+          "command": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "extensions": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "env": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "initialization": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "command"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Media.Image": {
+        "type": "object",
+        "properties": {
+          "auto_resize": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_width": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_height": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_base64_bytes": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Media": {
+        "type": "object",
+        "properties": {
+          "image": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Media.Image"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.ToolOutput": {
+        "type": "object",
+        "properties": {
+          "max_lines": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_bytes": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.MCP": {
+        "type": "object",
+        "properties": {
+          "timeout": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Mcp.TimeoutConfig"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "servers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "anyOf": [
+                    {
+                      "$ref": "#/components/schemas/Mcp.LocalConfig"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Mcp.RemoteConfig"
+                    }
+                  ]
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Compaction.Keep": {
+        "type": "object",
+        "properties": {
+          "tokens": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "minimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Compaction": {
+        "type": "object",
+        "properties": {
+          "auto": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "keep": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Compaction.Keep"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "buffer": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "minimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Command": {
+        "type": "object",
+        "properties": {
+          "template": {
+            "type": "string"
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "agent": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "model": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ModelSelection"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "subtask": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "template"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Reference.Git": {
+        "type": "object",
+        "properties": {
+          "repository": {
+            "type": "string"
+          },
+          "branch": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "hidden": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "repository"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Reference.Local": {
+        "type": "object",
+        "properties": {
+          "path": {
+            "type": "string"
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "hidden": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "ConfigWebSearch.Info": {
+        "type": "object",
+        "properties": {
+          "provider": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "provider"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Plugin.Entry": {
+        "type": "object",
+        "properties": {
+          "package": {
+            "type": "string"
+          },
+          "options": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "package"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Warming": {
+        "type": "object",
+        "properties": {
+          "prompt": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Prompt sent for keep-alive requests"
+          },
+          "interval": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Idle time between keep-alive requests (default: \"4 minutes\")"
+          },
+          "duration": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Time after the last active request to keep a session warm (default: \"30 minutes\")"
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Model.Cost.Cache": {
+        "type": "object",
+        "properties": {
+          "read": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "write": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Model.Cost": {
+        "type": "object",
+        "properties": {
+          "tier": {
+            "anyOf": [
+              {
+                "type": "object",
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "context"
+                    ]
+                  },
+                  "size": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "type",
+                  "size"
+                ],
+                "additionalProperties": false
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "input": {
+            "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+          },
+          "output": {
+            "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+          },
+          "cache": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Model.Cost.Cache"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "input",
+          "output"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Model.Limit": {
+        "type": "object",
+        "properties": {
+          "context": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "input": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "output": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Model": {
+        "type": "object",
+        "properties": {
+          "modelID": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "family": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "name": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "compatibility": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Model.Compatibility"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "package": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "settings": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "headers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "body": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "capabilities": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Model.Capabilities"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "variants": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "object",
+                  "properties": {
+                    "id": {
+                      "type": "string"
+                    },
+                    "settings": {
+                      "anyOf": [
+                        {
+                          "type": "object"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    },
+                    "headers": {
+                      "anyOf": [
+                        {
+                          "type": "object",
+                          "additionalProperties": {
+                            "type": "string"
+                          }
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    },
+                    "body": {
+                      "anyOf": [
+                        {
+                          "type": "object"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    }
+                  },
+                  "required": [
+                    "id"
+                  ],
+                  "additionalProperties": false
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "cost": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "$ref": "#/components/schemas/Config.Model.Cost"
+                  },
+                  {
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/components/schemas/Config.Model.Cost"
+                    }
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "limit": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Model.Limit"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Provider": {
+        "type": "object",
+        "properties": {
+          "name": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "env": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "package": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "settings": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "headers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "body": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "models": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Model"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "ConfigExperimental.Info": {
+        "type": "object",
+        "properties": {
+          "subagent_depth": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "minimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Maximum subagent nesting depth. Defaults to 1."
+          },
+          "policies": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "object",
+                  "properties": {
+                    "action": {
+                      "type": "string",
+                      "enum": [
+                        "provider.use"
+                      ]
+                    },
+                    "resource": {
+                      "type": "string"
+                    },
+                    "effect": {
+                      "type": "string",
+                      "enum": [
+                        "allow",
+                        "deny"
+                      ]
+                    }
+                  },
+                  "required": [
+                    "action",
+                    "resource",
+                    "effect"
+                  ],
+                  "additionalProperties": false
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Ordered policies controlling access to configured resources"
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Info": {
+        "type": "object",
+        "properties": {
+          "$schema": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "JSON schema reference for configuration validation"
+          },
+          "shell": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Default shell to use for terminal and shell tool execution"
+          },
+          "model": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ModelSelection"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Default model to use when no session or agent model is selected"
+          },
+          "default_agent": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Default primary agent to use when no session agent is selected"
+          },
+          "autoupdate": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "type": "string",
+                    "enum": [
+                      "notify"
+                    ]
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Automatically update or notify when a new version is available"
+          },
+          "share": {
+            "anyOf": [
+              {
+                "type": "string",
+                "enum": [
+                  "manual",
+                  "auto",
+                  "disabled"
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Control whether sessions may be shared manually, automatically, or not at all"
+          },
+          "enterprise": {
+            "anyOf": [
+              {
+                "type": "object",
+                "properties": {
+                  "url": {
+                    "anyOf": [
+                      {
+                        "type": "string"
+                      },
+                      {
+                        "type": "null"
+                      }
+                    ]
+                  }
+                },
+                "additionalProperties": false
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enterprise sharing service configuration"
+          },
+          "username": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Username displayed in conversations and used for telemetry identity"
+          },
+          "permissions": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Permission.Ruleset"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Ordered tool permission rules applied to agent tool use"
+          },
+          "agents": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Agent"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Named built-in agent overrides and custom agent definitions"
+          },
+          "snapshots": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enable snapshots used for undo and revert behavior"
+          },
+          "watcher": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Watcher"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Filesystem watcher configuration"
+          },
+          "formatter": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/components/schemas/Config.Formatter.Entry"
+                    }
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enable built-in formatters or configure formatter overrides"
+          },
+          "lsp": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "type": "object",
+                    "additionalProperties": {
+                      "anyOf": [
+                        {
+                          "type": "object",
+                          "properties": {
+                            "disabled": {
+                              "type": "boolean",
+                              "enum": [
+                                true
+                              ]
+                            }
+                          },
+                          "required": [
+                            "disabled"
+                          ],
+                          "additionalProperties": false
+                        },
+                        {
+                          "$ref": "#/components/schemas/Config.LSP.Server"
+                        }
+                      ]
+                    }
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enable built-in language servers or configure server overrides"
+          },
+          "media": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Media"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Media processing configuration"
+          },
+          "tool_output": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ToolOutput"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Tool output truncation thresholds"
+          },
+          "mcp": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.MCP"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "MCP server configuration"
+          },
+          "compaction": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Compaction"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Conversation compaction behavior"
+          },
+          "skills": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Additional paths or URLs to discover skills from"
+          },
+          "commands": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Command"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Named slash command definitions"
+          },
+          "instructions": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Additional paths or URLs supplying ambient instructions"
+          },
+          "references": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "anyOf": [
+                    {
+                      "type": "string"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Config.Reference.Git"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Config.Reference.Local"
+                    }
+                  ]
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Named local directories or Git repositories available as external context"
+          },
+          "websearch": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/ConfigWebSearch.Info"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Web search provider selection"
+          },
+          "plugins": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "anyOf": [
+                    {
+                      "type": "string"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Config.Plugin.Entry"
+                    }
+                  ]
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Ordered plugin enablement directives and external package declarations"
+          },
+          "warming": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "$ref": "#/components/schemas/Config.Warming"
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Keep recently active sessions warm with transient model requests (default: false)"
+          },
+          "providers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Provider"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "experimental": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/ConfigExperimental.Info"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Document": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "document"
+            ]
+          },
+          "path": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "info": {
+            "$ref": "#/components/schemas/Config.Info"
+          }
+        },
+        "required": [
+          "type",
+          "info"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Directory": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "directory"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.File": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "file"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.AgentsDirectory": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "agents"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.ClaudeDirectory": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "claude"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Entry": {
+        "anyOf": [
+          {
+            "$ref": "#/components/schemas/Config.Document"
+          },
+          {
+            "$ref": "#/components/schemas/Config.Directory"
+          },
+          {
+            "$ref": "#/components/schemas/Config.File"
+          },
+          {
+            "$ref": "#/components/schemas/Config.AgentsDirectory"
+          },
+          {
+            "$ref": "#/components/schemas/Config.ClaudeDirectory"
+          }
+        ]
+      }
+    },
+    "securitySchemes": {}
+  },
+  "security": [],
+  "tags": [
+    {
+      "name": "health"
+    },
+    {
+      "name": "server"
+    },
+    {
+      "name": "location"
+    },
+    {
+      "name": "agent"
+    },
+    {
+      "name": "plugin",
+      "description": "Experimental plugin routes."
+    },
+    {
+      "name": "session",
+      "description": "Experimental session routes."
+    },
+    {
+      "name": "session",
+      "description": "Experimental message routes."
+    },
+    {
+      "name": "model",
+      "description": "Experimental model routes."
+    },
+    {
+      "name": "generate",
+      "description": "Experimental one-shot generation routes."
+    },
+    {
+      "name": "provider",
+      "description": "Experimental provider routes."
+    },
+    {
+      "name": "integration",
+      "description": "Integration discovery and authentication routes."
+    },
+    {
+      "name": "mcp",
+      "description": "MCP server and resource routes."
+    },
+    {
+      "name": "credential"
+    },
+    {
+      "name": "project",
+      "description": "Location-scoped project routes."
+    },
+    {
+      "name": "form",
+      "description": "Session form routes."
+    },
+    {
+      "name": "permission",
+      "description": "Experimental permission routes."
+    },
+    {
+      "name": "filesystem",
+      "description": "Experimental location-scoped filesystem routes."
+    },
+    {
+      "name": "command",
+      "description": "Experimental command routes."
+    },
+    {
+      "name": "skill",
+      "description": "Experimental skill routes."
+    },
+    {
+      "name": "event",
+      "description": "Experimental event stream routes."
+    },
+    {
+      "name": "pty",
+      "description": "Experimental location-scoped PTY routes."
+    },
+    {
+      "name": "shell",
+      "description": "Experimental location-scoped shell command routes."
+    },
+    {
+      "name": "question",
+      "description": "Experimental session question routes."
+    },
+    {
+      "name": "reference",
+      "description": "Location-scoped project references."
+    },
+    {
+      "name": "projectCopy",
+      "description": "Project copy management routes."
+    },
+    {
+      "name": "vcs",
+      "description": "Location-scoped version control routes."
+    },
+    {
+      "name": "debug"
+    },
+    {
+      "name": "migration"
+    },
+    {
+      "name": "websearch",
+      "description": "Location-scoped web search routes."
+    },
+    {
+      "name": "config",
+      "description": "Location-scoped configuration routes."
     }
   ]
 }

+ 3 - 0
packages/protocol/src/api.ts

@@ -32,6 +32,7 @@ import { ProjectGroup } from "./groups/project.js"
 import { ProjectCopyGroup } from "./groups/project-copy.js"
 import { VcsGroup } from "./groups/vcs.js"
 import { MigrationGroup } from "./groups/migration.js"
+import { ConfigGroup } from "./groups/config.js"
 
 type LocationGroups<LocationId extends HttpApiMiddleware.AnyId> =
   | HttpApiGroup.AddMiddleware<typeof LocationGroup, LocationId>
@@ -53,6 +54,7 @@ type LocationGroups<LocationId extends HttpApiMiddleware.AnyId> =
   | HttpApiGroup.AddMiddleware<typeof ReferenceGroup, LocationId>
   | HttpApiGroup.AddMiddleware<typeof ProjectCopyGroup, LocationId>
   | HttpApiGroup.AddMiddleware<typeof VcsGroup, LocationId>
+  | HttpApiGroup.AddMiddleware<typeof ConfigGroup, LocationId>
 
 type SessionGroups<SessionLocationId extends HttpApiMiddleware.AnyId, SessionLocationService> =
   | ReturnType<typeof makeSessionGroup<SessionLocationId, SessionLocationService>>
@@ -175,6 +177,7 @@ const makeApiFromGroup = <
     .add(DebugGroup)
     .add(MigrationGroup)
     .add(WebSearchGroup.middleware(locationMiddleware))
+    .add(ConfigGroup.middleware(locationMiddleware))
     .annotateMerge(
       OpenApi.annotations({
         title: "opencode HttpApi",

+ 1 - 0
packages/protocol/src/client.ts

@@ -62,6 +62,7 @@ export const groupNames = {
   "server.project": "project",
   "server.projectCopy": "projectCopy",
   "server.vcs": "vcs",
+  "server.config": "config",
 } as const
 
 export const promiseOmitEndpoints = new Set(["pty.connect", "pty.connectToken"])

+ 22 - 0
packages/protocol/src/groups/config.ts

@@ -0,0 +1,22 @@
+import { Config } from "@opencode-ai/schema/config"
+import { Schema } from "effect"
+import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
+import { LocationQuery, locationQueryOpenApi } from "./location.js"
+
+export const ConfigGroup = HttpApiGroup.make("server.config")
+  .add(
+    HttpApiEndpoint.get("config.get", "/api/config", {
+      query: LocationQuery,
+      success: Schema.Array(Config.Entry),
+    })
+      .annotateMerge(locationQueryOpenApi)
+      .annotateMerge(
+        OpenApi.annotations({
+          identifier: "v2.config.get",
+          summary: "Get configuration",
+          description:
+            "Return configuration documents and discovery sources for the requested location, from lowest to highest priority.",
+        }),
+      ),
+  )
+  .annotateMerge(OpenApi.annotations({ title: "config", description: "Location-scoped configuration routes." }))

+ 136 - 0
packages/schema/src/config.ts

@@ -1,6 +1,142 @@
 export * as Config from "./config.js"
 
+import { Schema } from "effect"
 import { ephemeral, inventory } from "./event.js"
+import { Permission } from "./permission.js"
+import { AbsolutePath } from "./schema.js"
+import { ConfigAgent } from "./config/agent.js"
+import { ConfigMedia } from "./config/media.js"
+import { ConfigCompaction } from "./config/compaction.js"
+import { ConfigCommand } from "./config/command.js"
+import { ConfigExperimental } from "./config/experimental.js"
+import { ConfigFormatter } from "./config/formatter.js"
+import { ConfigLSP } from "./config/lsp.js"
+import { ConfigMCP } from "./config/mcp.js"
+import { ConfigModel } from "./config/model.js"
+import { ConfigPlugin } from "./config/plugin.js"
+import { ConfigProvider } from "./config/provider.js"
+import { ConfigReference } from "./config/reference.js"
+import { ConfigWebSearch } from "./config/websearch.js"
+import { ConfigToolOutput } from "./config/tool-output.js"
+import { ConfigWatcher } from "./config/watcher.js"
+import { ConfigWarming } from "./config/warming.js"
+
+export class Info extends Schema.Class<Info>("Config.Info")({
+  $schema: Schema.optional(Schema.String).annotate({
+    description: "JSON schema reference for configuration validation",
+  }),
+  shell: Schema.String.pipe(Schema.optional).annotate({
+    description: "Default shell to use for terminal and shell tool execution",
+  }),
+  model: ConfigModel.Selection.pipe(Schema.optional).annotate({
+    description: "Default model to use when no session or agent model is selected",
+  }),
+  default_agent: Schema.String.pipe(Schema.optional).annotate({
+    description: "Default primary agent to use when no session agent is selected",
+  }),
+  autoupdate: Schema.Union([Schema.Boolean, Schema.Literal("notify")])
+    .pipe(Schema.optional)
+    .annotate({
+      description: "Automatically update or notify when a new version is available",
+    }),
+  share: Schema.Literals(["manual", "auto", "disabled"]).pipe(Schema.optional).annotate({
+    description: "Control whether sessions may be shared manually, automatically, or not at all",
+  }),
+  enterprise: Schema.Struct({
+    url: Schema.String.pipe(Schema.optional),
+  })
+    .pipe(Schema.optional)
+    .annotate({
+      description: "Enterprise sharing service configuration",
+    }),
+  username: Schema.String.pipe(Schema.optional).annotate({
+    description: "Username displayed in conversations and used for telemetry identity",
+  }),
+  permissions: Permission.Ruleset.pipe(Schema.optional).annotate({
+    description: "Ordered tool permission rules applied to agent tool use",
+  }),
+  agents: Schema.Record(Schema.String, ConfigAgent.Info).pipe(Schema.optional).annotate({
+    description: "Named built-in agent overrides and custom agent definitions",
+  }),
+  snapshots: Schema.Boolean.pipe(Schema.optional).annotate({
+    description: "Enable snapshots used for undo and revert behavior",
+  }),
+  watcher: ConfigWatcher.Info.pipe(Schema.optional).annotate({
+    description: "Filesystem watcher configuration",
+  }),
+  formatter: ConfigFormatter.Info.pipe(Schema.optional).annotate({
+    description: "Enable built-in formatters or configure formatter overrides",
+  }),
+  lsp: ConfigLSP.Info.pipe(Schema.optional).annotate({
+    description: "Enable built-in language servers or configure server overrides",
+  }),
+  media: ConfigMedia.Info.pipe(Schema.optional).annotate({
+    description: "Media processing configuration",
+  }),
+  tool_output: ConfigToolOutput.Info.pipe(Schema.optional).annotate({
+    description: "Tool output truncation thresholds",
+  }),
+  mcp: ConfigMCP.Info.pipe(Schema.optional).annotate({
+    description: "MCP server configuration",
+  }),
+  compaction: ConfigCompaction.Info.pipe(Schema.optional).annotate({
+    description: "Conversation compaction behavior",
+  }),
+  skills: Schema.String.pipe(Schema.Array, Schema.optional).annotate({
+    description: "Additional paths or URLs to discover skills from",
+  }),
+  commands: Schema.Record(Schema.String, ConfigCommand.Info).pipe(Schema.optional).annotate({
+    description: "Named slash command definitions",
+  }),
+  instructions: Schema.String.pipe(Schema.Array, Schema.optional).annotate({
+    description: "Additional paths or URLs supplying ambient instructions",
+  }),
+  references: ConfigReference.Info.pipe(Schema.optional).annotate({
+    description: "Named local directories or Git repositories available as external context",
+  }),
+  websearch: ConfigWebSearch.Info.pipe(Schema.optional).annotate({
+    description: "Web search provider selection",
+  }),
+  plugins: ConfigPlugin.Plugins.pipe(Schema.optional).annotate({
+    description: "Ordered plugin enablement directives and external package declarations",
+  }),
+  warming: ConfigWarming.Warming.pipe(Schema.optional).annotate({
+    description: "Keep recently active sessions warm with transient model requests (default: false)",
+  }),
+  providers: Schema.Record(Schema.String, ConfigProvider.Info).pipe(Schema.optional),
+  experimental: ConfigExperimental.Info.pipe(Schema.optional),
+}) {}
+
+export class Document extends Schema.Class<Document>("Config.Document")({
+  type: Schema.Literal("document"),
+  path: Schema.String.pipe(Schema.optional),
+  info: Info,
+}) {}
+
+export class Directory extends Schema.Class<Directory>("Config.Directory")({
+  type: Schema.Literal("directory"),
+  path: AbsolutePath,
+}) {}
+
+export class File extends Schema.Class<File>("Config.File")({
+  type: Schema.Literal("file"),
+  path: AbsolutePath,
+}) {}
+
+export class AgentsDirectory extends Schema.Class<AgentsDirectory>("Config.AgentsDirectory")({
+  type: Schema.Literal("agents"),
+  path: AbsolutePath,
+}) {}
+
+export class ClaudeDirectory extends Schema.Class<ClaudeDirectory>("Config.ClaudeDirectory")({
+  type: Schema.Literal("claude"),
+  path: AbsolutePath,
+}) {}
+
+export const Entry = Schema.Union([Document, Directory, File, AgentsDirectory, ClaudeDirectory]).annotate({
+  identifier: "Config.Entry",
+})
+export type Entry = typeof Entry.Type
 
 const Updated = ephemeral({
   type: "config.updated",

+ 5 - 5
packages/core/src/config/agent.ts → packages/schema/src/config/agent.ts

@@ -1,10 +1,10 @@
-export * as ConfigAgent from "./agent"
+export * as ConfigAgent from "./agent.js"
 
 import { Schema } from "effect"
-import { Permission } from "@opencode-ai/schema/permission"
-import { ConfigProvider } from "./provider"
-import { ConfigModel } from "./model"
-import { PositiveInt } from "../schema"
+import { Permission } from "../permission.js"
+import { PositiveInt } from "../schema.js"
+import { ConfigModel } from "./model.js"
+import { ConfigProvider } from "./provider.js"
 
 export const Color = Schema.String.check(Schema.isPattern(/^#[0-9a-fA-F]{6}$/))
 

+ 2 - 2
packages/core/src/config/command.ts → packages/schema/src/config/command.ts

@@ -1,7 +1,7 @@
-export * as ConfigCommand from "./command"
+export * as ConfigCommand from "./command.js"
 
 import { Schema } from "effect"
-import { ConfigModel } from "./model"
+import { ConfigModel } from "./model.js"
 
 export class Info extends Schema.Class<Info>("Config.Command")({
   template: Schema.String,

+ 2 - 2
packages/core/src/config/compaction.ts → packages/schema/src/config/compaction.ts

@@ -1,7 +1,7 @@
-export * as ConfigCompaction from "./compaction"
+export * as ConfigCompaction from "./compaction.js"
 
 import { Schema } from "effect"
-import { NonNegativeInt } from "../schema"
+import { NonNegativeInt } from "../schema.js"
 
 export class Keep extends Schema.Class<Keep>("Config.Compaction.Keep")({
   tokens: NonNegativeInt.pipe(Schema.optional),

+ 3 - 3
packages/core/src/config/experimental.ts → packages/schema/src/config/experimental.ts

@@ -1,8 +1,8 @@
-export * as ConfigExperimental from "./experimental"
+export * as ConfigExperimental from "./experimental.js"
 
 import { Schema } from "effect"
-import { NonNegativeInt } from "../schema"
-import { ConfigPolicy } from "./policy"
+import { NonNegativeInt } from "../schema.js"
+import { ConfigPolicy } from "./policy.js"
 
 export class Info extends Schema.Class<Info>("ConfigExperimental.Info")({
   subagent_depth: NonNegativeInt.pipe(Schema.optional).annotate({

+ 1 - 1
packages/core/src/config/formatter.ts → packages/schema/src/config/formatter.ts

@@ -1,4 +1,4 @@
-export * as ConfigFormatter from "./formatter"
+export * as ConfigFormatter from "./formatter.js"
 
 import { Schema } from "effect"
 

+ 1 - 1
packages/core/src/config/lsp.ts → packages/schema/src/config/lsp.ts

@@ -1,4 +1,4 @@
-export * as ConfigLSP from "./lsp"
+export * as ConfigLSP from "./lsp.js"
 
 import { Schema } from "effect"
 

+ 2 - 4
packages/core/src/config/mcp.ts → packages/schema/src/config/mcp.ts

@@ -1,10 +1,8 @@
-export * as ConfigMCP from "./mcp"
+export * as ConfigMCP from "./mcp.js"
 
 import { Schema } from "effect"
-import { Mcp } from "@opencode-ai/schema/mcp"
+import { Mcp } from "../mcp.js"
 
-// The MCP server config is a public wire contract (used by the mcp.add route), so it lives in
-// @opencode-ai/schema and is re-exported here.
 export const Timeout = Mcp.TimeoutConfig
 export type Timeout = Mcp.TimeoutConfig
 export const Local = Mcp.LocalConfig

+ 2 - 2
packages/core/src/config/media.ts → packages/schema/src/config/media.ts

@@ -1,7 +1,7 @@
-export * as ConfigMedia from "./media"
+export * as ConfigMedia from "./media.js"
 
 import { Schema } from "effect"
-import { PositiveInt } from "../schema"
+import { PositiveInt } from "../schema.js"
 
 export class Image extends Schema.Class<Image>("Config.Media.Image")({
   auto_resize: Schema.Boolean.pipe(Schema.optional),

+ 3 - 3
packages/core/src/config/model.ts → packages/schema/src/config/model.ts

@@ -1,8 +1,8 @@
-export * as ConfigModel from "./model"
+export * as ConfigModel from "./model.js"
 
 import { Schema, SchemaGetter } from "effect"
-import { Model } from "@opencode-ai/schema/model"
-import { Provider } from "@opencode-ai/schema/provider"
+import { Model } from "../model.js"
+import { Provider } from "../provider.js"
 
 const ProviderID = Provider.ID.check(Schema.isPattern(/^[^/#]+$/))
 const ModelID = Model.ID.check(Schema.isPattern(/^[^#]+$/))

+ 1 - 1
packages/core/src/config/plugin.ts → packages/schema/src/config/plugin.ts

@@ -1,4 +1,4 @@
-export * as ConfigPlugin from "./plugin"
+export * as ConfigPlugin from "./plugin.js"
 
 import { Schema } from "effect"
 

+ 1 - 1
packages/core/src/config/policy.ts → packages/schema/src/config/policy.ts

@@ -1,4 +1,4 @@
-export * as ConfigPolicy from "./policy"
+export * as ConfigPolicy from "./policy.js"
 
 import { Schema } from "effect"
 

+ 3 - 3
packages/core/src/config/provider.ts → packages/schema/src/config/provider.ts

@@ -1,8 +1,8 @@
-export * as ConfigProvider from "./provider"
+export * as ConfigProvider from "./provider.js"
 
 import { Schema } from "effect"
-import { Money } from "@opencode-ai/schema/money"
-import { Capabilities, Compatibility, Family, ID, VariantID } from "../model"
+import { Money } from "../money.js"
+import { Capabilities, Compatibility, Family, ID, VariantID } from "../model.js"
 
 const JsonRecord = Schema.Record(Schema.String, Schema.Json)
 

+ 1 - 1
packages/core/src/config/reference.ts → packages/schema/src/config/reference.ts

@@ -1,4 +1,4 @@
-export * as ConfigReference from "./reference"
+export * as ConfigReference from "./reference.js"
 
 import { Schema } from "effect"
 

+ 2 - 2
packages/core/src/config/tool-output.ts → packages/schema/src/config/tool-output.ts

@@ -1,7 +1,7 @@
-export * as ConfigToolOutput from "./tool-output"
+export * as ConfigToolOutput from "./tool-output.js"
 
 import { Schema } from "effect"
-import { PositiveInt } from "../schema"
+import { PositiveInt } from "../schema.js"
 
 export class Info extends Schema.Class<Info>("Config.ToolOutput")({
   max_lines: PositiveInt.pipe(Schema.optional),

+ 1 - 1
packages/core/src/config/warming.ts → packages/schema/src/config/warming.ts

@@ -1,4 +1,4 @@
-export * as ConfigWarming from "./warming"
+export * as ConfigWarming from "./warming.js"
 
 import { Schema } from "effect"
 

+ 1 - 1
packages/core/src/config/watcher.ts → packages/schema/src/config/watcher.ts

@@ -1,4 +1,4 @@
-export * as ConfigWatcher from "./watcher"
+export * as ConfigWatcher from "./watcher.js"
 
 import { Schema } from "effect"
 

+ 2 - 2
packages/core/src/config/websearch.ts → packages/schema/src/config/websearch.ts

@@ -1,7 +1,7 @@
-export * as ConfigWebSearch from "./websearch"
+export * as ConfigWebSearch from "./websearch.js"
 
-import { WebSearch } from "@opencode-ai/schema/websearch"
 import { Schema } from "effect"
+import { WebSearch } from "../websearch.js"
 
 export class Info extends Schema.Class<Info>("ConfigWebSearch.Info")({
   provider: WebSearch.ID,

+ 42 - 0
packages/schema/test/config.test.ts

@@ -0,0 +1,42 @@
+import { describe, expect, test } from "bun:test"
+import { Schema } from "effect"
+import { Config } from "../src/config.js"
+import { AbsolutePath } from "../src/schema.js"
+
+describe("Config.Entry", () => {
+  test("round-trips every configuration entry type", () => {
+    const entries = [
+      new Config.Document({
+        type: "document",
+        path: "/project/opencode.json",
+        info: new Config.Info({
+          permissions: [
+            { action: "shell", resource: "*", effect: "ask" },
+            { action: "shell", resource: "git status", effect: "allow" },
+          ],
+        }),
+      }),
+      new Config.Document({ type: "document", info: new Config.Info({ shell: "/bin/zsh" }) }),
+      new Config.Directory({ type: "directory", path: AbsolutePath.make("/project/.opencode") }),
+      new Config.File({ type: "file", path: AbsolutePath.make("/project/opencode.json") }),
+      new Config.AgentsDirectory({ type: "agents", path: AbsolutePath.make("/project/.agents") }),
+      new Config.ClaudeDirectory({ type: "claude", path: AbsolutePath.make("/project/.claude") }),
+    ]
+
+    const encoded = Schema.encodeSync(Schema.Array(Config.Entry))(entries)
+    const decoded = Schema.decodeUnknownSync(Schema.Array(Config.Entry))(encoded)
+
+    expect(decoded).toEqual(entries)
+    expect(decoded[0]).toBeInstanceOf(Config.Document)
+    expect(decoded[1]).not.toHaveProperty("path")
+    expect(decoded.map((entry) => entry.type)).toEqual(["document", "document", "directory", "file", "agents", "claude"])
+    expect(decoded[0]?.type === "document" ? decoded[0].info.permissions : undefined).toEqual([
+      { action: "shell", resource: "*", effect: "ask" },
+      { action: "shell", resource: "git status", effect: "allow" },
+    ])
+  })
+
+  test("has a stable public identifier", () => {
+    expect(Config.Entry.ast.annotations?.identifier).toBe("Config.Entry")
+  })
+})

+ 1 - 0
packages/sdk-next/src/index.ts

@@ -5,6 +5,7 @@ export { ClientError } from "@opencode-ai/client/effect"
 export type { OpenCodeEvent } from "@opencode-ai/client/effect"
 export { Agent } from "@opencode-ai/schema/agent"
 export { Command } from "@opencode-ai/schema/command"
+export { Config } from "@opencode-ai/schema/config"
 export { Credential } from "@opencode-ai/schema/credential"
 export { FileSystem } from "@opencode-ai/schema/filesystem"
 export { Integration } from "@opencode-ai/schema/integration"

+ 3 - 0
packages/sdk-next/test/contract-identity.test.ts

@@ -3,6 +3,7 @@ import { Location as CoreLocation } from "@opencode-ai/core/location"
 import { SessionPending as CoreSessionPending } from "@opencode-ai/core/session/pending"
 import { SessionMessage as CoreSessionMessage } from "@opencode-ai/core/session/message"
 import { Agent } from "@opencode-ai/schema/agent"
+import { Config } from "@opencode-ai/schema/config"
 import { Location } from "@opencode-ai/schema/location"
 import { Model } from "@opencode-ai/schema/model"
 import { Project } from "@opencode-ai/schema/project"
@@ -24,6 +25,7 @@ const CoreSession = await import("@opencode-ai/core/session")
 
 test("re-exports canonical contracts directly from Schema", () => {
   expect(SDK.Agent).toBe(Agent)
+  expect(SDK.Config).toBe(Config)
   expect(SDK.Model).toBe(Model)
   expect(SDK.WebSearch).toBe(WebSearch)
   expect(SDK.Session).toBe(Session)
@@ -32,6 +34,7 @@ test("re-exports canonical contracts directly from Schema", () => {
     "Agent",
     "ClientError",
     "Command",
+    "Config",
     "Credential",
     "FileSystem",
     "Integration",

+ 2 - 0
packages/server/src/handlers.ts

@@ -29,6 +29,7 @@ import { ProjectCopyHandler } from "./handlers/project-copy"
 import { VcsHandler } from "./handlers/vcs"
 import { EventFeed } from "./event-feed"
 import { MigrationHandler } from "./handlers/migration"
+import { ConfigHandler } from "./handlers/config"
 
 export const handlers = Layer.mergeAll(
   HealthHandler,
@@ -60,4 +61,5 @@ export const handlers = Layer.mergeAll(
   ReferenceHandler,
   ProjectCopyHandler,
   VcsHandler,
+  ConfigHandler,
 )

+ 7 - 0
packages/server/src/handlers/config.ts

@@ -0,0 +1,7 @@
+import { Config } from "@opencode-ai/core/config"
+import { HttpApiBuilder } from "effect/unstable/httpapi"
+import { Api } from "../api"
+
+export const ConfigHandler = HttpApiBuilder.group(Api, "server.config", (handlers) =>
+  handlers.handle("config.get", () => Config.Service.use((config) => config.entries())),
+)

+ 62 - 0
packages/server/test/config.test.ts

@@ -0,0 +1,62 @@
+import fs from "node:fs/promises"
+import path from "node:path"
+import { expect } from "bun:test"
+import { Config } from "@opencode-ai/schema/config"
+import { Effect, Schema } from "effect"
+import { HttpServer } from "effect/unstable/http"
+import { tmpdir } from "../../core/test/fixture/tmpdir"
+import { it } from "../../core/test/lib/effect"
+import { ServerProcess } from "../src/process"
+
+it.live("returns ordered config entries for the requested directory", () =>
+  Effect.acquireUseRelease(
+    Effect.promise(() => tmpdir("opencode-config-endpoint-")),
+    (tmp) =>
+      Effect.gen(function* () {
+        const global = path.join(tmp.path, "global")
+        const project = path.join(tmp.path, "project")
+        const config = path.join(project, "opencode.json")
+        yield* Effect.promise(() => Promise.all([fs.mkdir(global, { recursive: true }), fs.mkdir(project, { recursive: true })]))
+        yield* Effect.promise(() =>
+          fs.writeFile(
+            config,
+            JSON.stringify({
+              permissions: [
+                { action: "shell", resource: "*", effect: "ask" },
+                { action: "shell", resource: "git status", effect: "allow" },
+              ],
+            }),
+          ),
+        )
+        const server = yield* ServerProcess.start<never, never>({
+          hostname: "127.0.0.1",
+          port: 0,
+          password: "secret",
+          app: { version: "test-version" },
+          database: { path: ":memory:" },
+          config: { directory: global },
+          fs: { filewatcher: false },
+        })
+        const url = new URL("/api/config", HttpServer.formatAddress(server.address))
+        url.searchParams.set("location[directory]", project)
+        const response = yield* Effect.promise(() =>
+          fetch(url, { headers: { authorization: `Basic ${btoa("opencode:secret")}` } }),
+        )
+        const entries = Schema.decodeUnknownSync(Schema.Array(Config.Entry))(
+          yield* Effect.promise(() => response.json()),
+        )
+
+        expect(response.status).toBe(200)
+        expect(Array.isArray(entries)).toBe(true)
+        const document = entries.find(
+          (entry): entry is Config.Document => entry.type === "document" && entry.path === config,
+        )
+        expect(document?.info.permissions).toEqual([
+          { action: "shell", resource: "*", effect: "ask" },
+          { action: "shell", resource: "git status", effect: "allow" },
+        ])
+        expect(entries.some((entry) => entry.type === "file" && entry.path === config)).toBe(true)
+      }),
+    (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()),
+  ),
+)

+ 2045 - 249
packages/www/openapi.json

@@ -1025,14 +1025,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -1540,14 +1533,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -2912,14 +2898,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -3009,14 +2988,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -3586,14 +3558,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -3820,14 +3785,11 @@
               "application/json": {
                 "schema": {
                   "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/MessageNotFoundError"
-                    },
                     {
                       "$ref": "#/components/schemas/SessionNotFoundError"
                     },
                     {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
+                      "$ref": "#/components/schemas/MessageNotFoundError"
                     }
                   ]
                 }
@@ -3956,14 +3918,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -11771,39 +11726,101 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "type": "object",
-                  "properties": {
-                    "status": {
-                      "type": "string",
-                      "enum": [
-                        "required",
-                        "running",
-                        "completed"
-                      ]
+                  "anyOf": [
+                    {
+                      "type": "object",
+                      "properties": {
+                        "status": {
+                          "type": "string",
+                          "enum": [
+                            "required",
+                            "completed"
+                          ]
+                        }
+                      },
+                      "required": [
+                        "status"
+                      ],
+                      "additionalProperties": false
                     },
-                    "completed": {
-                      "type": "integer",
-                      "allOf": [
-                        {
-                          "minimum": 0
+                    {
+                      "type": "object",
+                      "properties": {
+                        "status": {
+                          "type": "string",
+                          "enum": [
+                            "running"
+                          ]
+                        },
+                        "progress": {
+                          "type": "object",
+                          "properties": {
+                            "label": {
+                              "type": "string"
+                            },
+                            "numerator": {
+                              "anyOf": [
+                                {
+                                  "type": "integer",
+                                  "allOf": [
+                                    {
+                                      "minimum": 0
+                                    }
+                                  ]
+                                },
+                                {
+                                  "type": "null"
+                                }
+                              ]
+                            },
+                            "denominator": {
+                              "anyOf": [
+                                {
+                                  "type": "integer",
+                                  "allOf": [
+                                    {
+                                      "minimum": 0
+                                    }
+                                  ]
+                                },
+                                {
+                                  "type": "null"
+                                }
+                              ]
+                            }
+                          },
+                          "required": [
+                            "label"
+                          ],
+                          "additionalProperties": false
                         }
-                      ]
+                      },
+                      "required": [
+                        "status",
+                        "progress"
+                      ],
+                      "additionalProperties": false
                     },
-                    "total": {
-                      "type": "integer",
-                      "allOf": [
-                        {
-                          "minimum": 0
+                    {
+                      "type": "object",
+                      "properties": {
+                        "status": {
+                          "type": "string",
+                          "enum": [
+                            "error"
+                          ]
+                        },
+                        "error": {
+                          "type": "string"
                         }
-                      ]
+                      },
+                      "required": [
+                        "status",
+                        "error"
+                      ],
+                      "additionalProperties": false
                     }
-                  },
-                  "required": [
-                    "status",
-                    "completed",
-                    "total"
-                  ],
-                  "additionalProperties": false
+                  ]
                 }
               }
             }
@@ -11831,60 +11848,6 @@
         },
         "description": "Return the progress of the V1 to V2 session history migration.",
         "summary": "Get V1 migration status"
-      },
-      "post": {
-        "tags": [
-          "migration"
-        ],
-        "operationId": "v2.experimental.migration.v1.run",
-        "parameters": [],
-        "security": [],
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "type": "object",
-                  "properties": {
-                    "status": {
-                      "type": "string",
-                      "enum": [
-                        "completed"
-                      ]
-                    }
-                  },
-                  "required": [
-                    "status"
-                  ],
-                  "additionalProperties": false
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "InvalidRequestError",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/InvalidRequestError"
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "UnauthorizedError",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/UnauthorizedError"
-                }
-              }
-            }
-          }
-        },
-        "description": "Run or resume the V1 to V2 session history migration and wait for completion.",
-        "summary": "Run V1 migration"
       }
     },
     "/api/websearch/provider": {
@@ -12134,6 +12097,94 @@
           "required": true
         }
       }
+    },
+    "/api/config": {
+      "get": {
+        "tags": [
+          "config"
+        ],
+        "operationId": "v2.config.get",
+        "parameters": [
+          {
+            "name": "location",
+            "in": "query",
+            "schema": {
+              "anyOf": [
+                {
+                  "type": "object",
+                  "properties": {
+                    "directory": {
+                      "anyOf": [
+                        {
+                          "type": "string"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    },
+                    "workspace": {
+                      "anyOf": [
+                        {
+                          "type": "string"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    }
+                  },
+                  "additionalProperties": false
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "required": false,
+            "style": "deepObject",
+            "explode": true
+          }
+        ],
+        "security": [],
+        "responses": {
+          "200": {
+            "description": "Success",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/Config.Entry"
+                  }
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "InvalidRequestError",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/InvalidRequestError"
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "UnauthorizedError",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UnauthorizedError"
+                }
+              }
+            }
+          }
+        },
+        "description": "Return configuration documents and discovery sources for the requested location, from lowest to highest priority.",
+        "summary": "Get configuration"
+      }
     }
   },
   "components": {
@@ -16014,7 +16065,10 @@
                     }
                   ]
                 }
-              }
+              },
+              "text": {
+                "type": "string"
+              }
             },
             "required": [
               "sessionID",
@@ -26457,120 +26511,1862 @@
           "results"
         ],
         "additionalProperties": false
-      }
-    },
-    "securitySchemes": {}
-  },
-  "security": [],
-  "tags": [
-    {
-      "name": "health"
-    },
-    {
-      "name": "server"
-    },
-    {
-      "name": "location"
-    },
-    {
-      "name": "agent"
-    },
-    {
-      "name": "plugin",
-      "description": "Experimental plugin routes."
-    },
-    {
-      "name": "session",
-      "description": "Experimental session routes."
-    },
-    {
-      "name": "session",
-      "description": "Experimental message routes."
-    },
-    {
-      "name": "model",
-      "description": "Experimental model routes."
-    },
-    {
-      "name": "generate",
-      "description": "Experimental one-shot generation routes."
-    },
-    {
-      "name": "provider",
-      "description": "Experimental provider routes."
-    },
-    {
-      "name": "integration",
-      "description": "Integration discovery and authentication routes."
-    },
-    {
-      "name": "mcp",
-      "description": "MCP server and resource routes."
-    },
-    {
-      "name": "credential"
-    },
-    {
-      "name": "project",
-      "description": "Location-scoped project routes."
-    },
-    {
-      "name": "form",
-      "description": "Session form routes."
-    },
-    {
-      "name": "permission",
-      "description": "Experimental permission routes."
-    },
-    {
-      "name": "filesystem",
-      "description": "Experimental location-scoped filesystem routes."
-    },
-    {
-      "name": "command",
-      "description": "Experimental command routes."
-    },
-    {
-      "name": "skill",
-      "description": "Experimental skill routes."
-    },
-    {
-      "name": "event",
-      "description": "Experimental event stream routes."
-    },
-    {
-      "name": "pty",
-      "description": "Experimental location-scoped PTY routes."
-    },
-    {
-      "name": "shell",
-      "description": "Experimental location-scoped shell command routes."
-    },
-    {
-      "name": "question",
-      "description": "Experimental session question routes."
-    },
-    {
-      "name": "reference",
-      "description": "Location-scoped project references."
-    },
-    {
-      "name": "projectCopy",
-      "description": "Project copy management routes."
-    },
-    {
-      "name": "vcs",
-      "description": "Location-scoped version control routes."
-    },
-    {
-      "name": "debug"
-    },
-    {
-      "name": "migration"
-    },
-    {
-      "name": "websearch",
-      "description": "Location-scoped web search routes."
+      },
+      "Config.ModelSelection": {
+        "anyOf": [
+          {
+            "type": "string",
+            "allOf": [
+              {
+                "pattern": "^[^/#]+\\/[^#]+(?:#[^#]+)?$"
+              }
+            ]
+          },
+          {
+            "type": "object",
+            "properties": {
+              "providerID": {
+                "type": "string",
+                "allOf": [
+                  {
+                    "pattern": "^[^/#]+$"
+                  }
+                ]
+              },
+              "model": {
+                "type": "string",
+                "allOf": [
+                  {
+                    "pattern": "^[^#]+$"
+                  }
+                ]
+              },
+              "variant": {
+                "anyOf": [
+                  {
+                    "type": "string",
+                    "allOf": [
+                      {
+                        "pattern": "^[^#]+$"
+                      }
+                    ]
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            },
+            "required": [
+              "providerID",
+              "model"
+            ],
+            "additionalProperties": false
+          }
+        ]
+      },
+      "Config.Provider.Request": {
+        "type": "object",
+        "properties": {
+          "headers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "body": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Agent": {
+        "type": "object",
+        "properties": {
+          "model": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ModelSelection"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "request": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Provider.Request"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "system": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "mode": {
+            "anyOf": [
+              {
+                "type": "string",
+                "enum": [
+                  "subagent",
+                  "primary",
+                  "all"
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "hidden": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "color": {
+            "anyOf": [
+              {
+                "type": "string",
+                "allOf": [
+                  {
+                    "pattern": "^#[0-9a-fA-F]{6}$"
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "steps": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "permissions": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Permission.Ruleset"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Watcher": {
+        "type": "object",
+        "properties": {
+          "ignore": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Formatter.Entry": {
+        "type": "object",
+        "properties": {
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "command": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "environment": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "extensions": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.LSP.Server": {
+        "type": "object",
+        "properties": {
+          "command": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "extensions": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "env": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "initialization": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "command"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Media.Image": {
+        "type": "object",
+        "properties": {
+          "auto_resize": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_width": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_height": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_base64_bytes": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Media": {
+        "type": "object",
+        "properties": {
+          "image": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Media.Image"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.ToolOutput": {
+        "type": "object",
+        "properties": {
+          "max_lines": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_bytes": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.MCP": {
+        "type": "object",
+        "properties": {
+          "timeout": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Mcp.TimeoutConfig"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "servers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "anyOf": [
+                    {
+                      "$ref": "#/components/schemas/Mcp.LocalConfig"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Mcp.RemoteConfig"
+                    }
+                  ]
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Compaction.Keep": {
+        "type": "object",
+        "properties": {
+          "tokens": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "minimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Compaction": {
+        "type": "object",
+        "properties": {
+          "auto": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "keep": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Compaction.Keep"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "buffer": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "minimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Command": {
+        "type": "object",
+        "properties": {
+          "template": {
+            "type": "string"
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "agent": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "model": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ModelSelection"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "subtask": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "template"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Reference.Git": {
+        "type": "object",
+        "properties": {
+          "repository": {
+            "type": "string"
+          },
+          "branch": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "hidden": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "repository"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Reference.Local": {
+        "type": "object",
+        "properties": {
+          "path": {
+            "type": "string"
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "hidden": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "ConfigWebSearch.Info": {
+        "type": "object",
+        "properties": {
+          "provider": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "provider"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Plugin.Entry": {
+        "type": "object",
+        "properties": {
+          "package": {
+            "type": "string"
+          },
+          "options": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "package"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Warming": {
+        "type": "object",
+        "properties": {
+          "prompt": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Prompt sent for keep-alive requests"
+          },
+          "interval": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Idle time between keep-alive requests (default: \"4 minutes\")"
+          },
+          "duration": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Time after the last active request to keep a session warm (default: \"30 minutes\")"
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Model.Cost.Cache": {
+        "type": "object",
+        "properties": {
+          "read": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "write": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Model.Cost": {
+        "type": "object",
+        "properties": {
+          "tier": {
+            "anyOf": [
+              {
+                "type": "object",
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "context"
+                    ]
+                  },
+                  "size": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "type",
+                  "size"
+                ],
+                "additionalProperties": false
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "input": {
+            "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+          },
+          "output": {
+            "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+          },
+          "cache": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Model.Cost.Cache"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "input",
+          "output"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Model.Limit": {
+        "type": "object",
+        "properties": {
+          "context": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "input": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "output": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Model": {
+        "type": "object",
+        "properties": {
+          "modelID": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "family": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "name": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "compatibility": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Model.Compatibility"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "package": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "settings": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "headers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "body": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "capabilities": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Model.Capabilities"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "variants": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "object",
+                  "properties": {
+                    "id": {
+                      "type": "string"
+                    },
+                    "settings": {
+                      "anyOf": [
+                        {
+                          "type": "object"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    },
+                    "headers": {
+                      "anyOf": [
+                        {
+                          "type": "object",
+                          "additionalProperties": {
+                            "type": "string"
+                          }
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    },
+                    "body": {
+                      "anyOf": [
+                        {
+                          "type": "object"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    }
+                  },
+                  "required": [
+                    "id"
+                  ],
+                  "additionalProperties": false
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "cost": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "$ref": "#/components/schemas/Config.Model.Cost"
+                  },
+                  {
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/components/schemas/Config.Model.Cost"
+                    }
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "limit": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Model.Limit"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Provider": {
+        "type": "object",
+        "properties": {
+          "name": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "env": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "package": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "settings": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "headers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "body": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "models": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Model"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "ConfigExperimental.Info": {
+        "type": "object",
+        "properties": {
+          "subagent_depth": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "minimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Maximum subagent nesting depth. Defaults to 1."
+          },
+          "policies": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "object",
+                  "properties": {
+                    "action": {
+                      "type": "string",
+                      "enum": [
+                        "provider.use"
+                      ]
+                    },
+                    "resource": {
+                      "type": "string"
+                    },
+                    "effect": {
+                      "type": "string",
+                      "enum": [
+                        "allow",
+                        "deny"
+                      ]
+                    }
+                  },
+                  "required": [
+                    "action",
+                    "resource",
+                    "effect"
+                  ],
+                  "additionalProperties": false
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Ordered policies controlling access to configured resources"
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Info": {
+        "type": "object",
+        "properties": {
+          "$schema": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "JSON schema reference for configuration validation"
+          },
+          "shell": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Default shell to use for terminal and shell tool execution"
+          },
+          "model": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ModelSelection"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Default model to use when no session or agent model is selected"
+          },
+          "default_agent": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Default primary agent to use when no session agent is selected"
+          },
+          "autoupdate": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "type": "string",
+                    "enum": [
+                      "notify"
+                    ]
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Automatically update or notify when a new version is available"
+          },
+          "share": {
+            "anyOf": [
+              {
+                "type": "string",
+                "enum": [
+                  "manual",
+                  "auto",
+                  "disabled"
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Control whether sessions may be shared manually, automatically, or not at all"
+          },
+          "enterprise": {
+            "anyOf": [
+              {
+                "type": "object",
+                "properties": {
+                  "url": {
+                    "anyOf": [
+                      {
+                        "type": "string"
+                      },
+                      {
+                        "type": "null"
+                      }
+                    ]
+                  }
+                },
+                "additionalProperties": false
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enterprise sharing service configuration"
+          },
+          "username": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Username displayed in conversations and used for telemetry identity"
+          },
+          "permissions": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Permission.Ruleset"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Ordered tool permission rules applied to agent tool use"
+          },
+          "agents": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Agent"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Named built-in agent overrides and custom agent definitions"
+          },
+          "snapshots": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enable snapshots used for undo and revert behavior"
+          },
+          "watcher": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Watcher"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Filesystem watcher configuration"
+          },
+          "formatter": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/components/schemas/Config.Formatter.Entry"
+                    }
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enable built-in formatters or configure formatter overrides"
+          },
+          "lsp": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "type": "object",
+                    "additionalProperties": {
+                      "anyOf": [
+                        {
+                          "type": "object",
+                          "properties": {
+                            "disabled": {
+                              "type": "boolean",
+                              "enum": [
+                                true
+                              ]
+                            }
+                          },
+                          "required": [
+                            "disabled"
+                          ],
+                          "additionalProperties": false
+                        },
+                        {
+                          "$ref": "#/components/schemas/Config.LSP.Server"
+                        }
+                      ]
+                    }
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enable built-in language servers or configure server overrides"
+          },
+          "media": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Media"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Media processing configuration"
+          },
+          "tool_output": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ToolOutput"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Tool output truncation thresholds"
+          },
+          "mcp": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.MCP"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "MCP server configuration"
+          },
+          "compaction": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Compaction"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Conversation compaction behavior"
+          },
+          "skills": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Additional paths or URLs to discover skills from"
+          },
+          "commands": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Command"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Named slash command definitions"
+          },
+          "instructions": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Additional paths or URLs supplying ambient instructions"
+          },
+          "references": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "anyOf": [
+                    {
+                      "type": "string"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Config.Reference.Git"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Config.Reference.Local"
+                    }
+                  ]
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Named local directories or Git repositories available as external context"
+          },
+          "websearch": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/ConfigWebSearch.Info"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Web search provider selection"
+          },
+          "plugins": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "anyOf": [
+                    {
+                      "type": "string"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Config.Plugin.Entry"
+                    }
+                  ]
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Ordered plugin enablement directives and external package declarations"
+          },
+          "warming": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "$ref": "#/components/schemas/Config.Warming"
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Keep recently active sessions warm with transient model requests (default: false)"
+          },
+          "providers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Provider"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "experimental": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/ConfigExperimental.Info"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Document": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "document"
+            ]
+          },
+          "path": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "info": {
+            "$ref": "#/components/schemas/Config.Info"
+          }
+        },
+        "required": [
+          "type",
+          "info"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Directory": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "directory"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.File": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "file"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.AgentsDirectory": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "agents"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.ClaudeDirectory": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "claude"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Entry": {
+        "anyOf": [
+          {
+            "$ref": "#/components/schemas/Config.Document"
+          },
+          {
+            "$ref": "#/components/schemas/Config.Directory"
+          },
+          {
+            "$ref": "#/components/schemas/Config.File"
+          },
+          {
+            "$ref": "#/components/schemas/Config.AgentsDirectory"
+          },
+          {
+            "$ref": "#/components/schemas/Config.ClaudeDirectory"
+          }
+        ]
+      }
+    },
+    "securitySchemes": {}
+  },
+  "security": [],
+  "tags": [
+    {
+      "name": "health"
+    },
+    {
+      "name": "server"
+    },
+    {
+      "name": "location"
+    },
+    {
+      "name": "agent"
+    },
+    {
+      "name": "plugin",
+      "description": "Experimental plugin routes."
+    },
+    {
+      "name": "session",
+      "description": "Experimental session routes."
+    },
+    {
+      "name": "session",
+      "description": "Experimental message routes."
+    },
+    {
+      "name": "model",
+      "description": "Experimental model routes."
+    },
+    {
+      "name": "generate",
+      "description": "Experimental one-shot generation routes."
+    },
+    {
+      "name": "provider",
+      "description": "Experimental provider routes."
+    },
+    {
+      "name": "integration",
+      "description": "Integration discovery and authentication routes."
+    },
+    {
+      "name": "mcp",
+      "description": "MCP server and resource routes."
+    },
+    {
+      "name": "credential"
+    },
+    {
+      "name": "project",
+      "description": "Location-scoped project routes."
+    },
+    {
+      "name": "form",
+      "description": "Session form routes."
+    },
+    {
+      "name": "permission",
+      "description": "Experimental permission routes."
+    },
+    {
+      "name": "filesystem",
+      "description": "Experimental location-scoped filesystem routes."
+    },
+    {
+      "name": "command",
+      "description": "Experimental command routes."
+    },
+    {
+      "name": "skill",
+      "description": "Experimental skill routes."
+    },
+    {
+      "name": "event",
+      "description": "Experimental event stream routes."
+    },
+    {
+      "name": "pty",
+      "description": "Experimental location-scoped PTY routes."
+    },
+    {
+      "name": "shell",
+      "description": "Experimental location-scoped shell command routes."
+    },
+    {
+      "name": "question",
+      "description": "Experimental session question routes."
+    },
+    {
+      "name": "reference",
+      "description": "Location-scoped project references."
+    },
+    {
+      "name": "projectCopy",
+      "description": "Project copy management routes."
+    },
+    {
+      "name": "vcs",
+      "description": "Location-scoped version control routes."
+    },
+    {
+      "name": "debug"
+    },
+    {
+      "name": "migration"
+    },
+    {
+      "name": "websearch",
+      "description": "Location-scoped web search routes."
+    },
+    {
+      "name": "config",
+      "description": "Location-scoped configuration routes."
     }
   ]
 }

+ 2045 - 249
packages/www/public/openapi.json

@@ -1025,14 +1025,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -1540,14 +1533,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -2912,14 +2898,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -3009,14 +2988,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -3586,14 +3558,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -3820,14 +3785,11 @@
               "application/json": {
                 "schema": {
                   "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/MessageNotFoundError"
-                    },
                     {
                       "$ref": "#/components/schemas/SessionNotFoundError"
                     },
                     {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
+                      "$ref": "#/components/schemas/MessageNotFoundError"
                     }
                   ]
                 }
@@ -3956,14 +3918,7 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "anyOf": [
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    },
-                    {
-                      "$ref": "#/components/schemas/SessionNotFoundError"
-                    }
-                  ]
+                  "$ref": "#/components/schemas/SessionNotFoundError"
                 }
               }
             }
@@ -11771,39 +11726,101 @@
             "content": {
               "application/json": {
                 "schema": {
-                  "type": "object",
-                  "properties": {
-                    "status": {
-                      "type": "string",
-                      "enum": [
-                        "required",
-                        "running",
-                        "completed"
-                      ]
+                  "anyOf": [
+                    {
+                      "type": "object",
+                      "properties": {
+                        "status": {
+                          "type": "string",
+                          "enum": [
+                            "required",
+                            "completed"
+                          ]
+                        }
+                      },
+                      "required": [
+                        "status"
+                      ],
+                      "additionalProperties": false
                     },
-                    "completed": {
-                      "type": "integer",
-                      "allOf": [
-                        {
-                          "minimum": 0
+                    {
+                      "type": "object",
+                      "properties": {
+                        "status": {
+                          "type": "string",
+                          "enum": [
+                            "running"
+                          ]
+                        },
+                        "progress": {
+                          "type": "object",
+                          "properties": {
+                            "label": {
+                              "type": "string"
+                            },
+                            "numerator": {
+                              "anyOf": [
+                                {
+                                  "type": "integer",
+                                  "allOf": [
+                                    {
+                                      "minimum": 0
+                                    }
+                                  ]
+                                },
+                                {
+                                  "type": "null"
+                                }
+                              ]
+                            },
+                            "denominator": {
+                              "anyOf": [
+                                {
+                                  "type": "integer",
+                                  "allOf": [
+                                    {
+                                      "minimum": 0
+                                    }
+                                  ]
+                                },
+                                {
+                                  "type": "null"
+                                }
+                              ]
+                            }
+                          },
+                          "required": [
+                            "label"
+                          ],
+                          "additionalProperties": false
                         }
-                      ]
+                      },
+                      "required": [
+                        "status",
+                        "progress"
+                      ],
+                      "additionalProperties": false
                     },
-                    "total": {
-                      "type": "integer",
-                      "allOf": [
-                        {
-                          "minimum": 0
+                    {
+                      "type": "object",
+                      "properties": {
+                        "status": {
+                          "type": "string",
+                          "enum": [
+                            "error"
+                          ]
+                        },
+                        "error": {
+                          "type": "string"
                         }
-                      ]
+                      },
+                      "required": [
+                        "status",
+                        "error"
+                      ],
+                      "additionalProperties": false
                     }
-                  },
-                  "required": [
-                    "status",
-                    "completed",
-                    "total"
-                  ],
-                  "additionalProperties": false
+                  ]
                 }
               }
             }
@@ -11831,60 +11848,6 @@
         },
         "description": "Return the progress of the V1 to V2 session history migration.",
         "summary": "Get V1 migration status"
-      },
-      "post": {
-        "tags": [
-          "migration"
-        ],
-        "operationId": "v2.experimental.migration.v1.run",
-        "parameters": [],
-        "security": [],
-        "responses": {
-          "200": {
-            "description": "Success",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "type": "object",
-                  "properties": {
-                    "status": {
-                      "type": "string",
-                      "enum": [
-                        "completed"
-                      ]
-                    }
-                  },
-                  "required": [
-                    "status"
-                  ],
-                  "additionalProperties": false
-                }
-              }
-            }
-          },
-          "400": {
-            "description": "InvalidRequestError",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/InvalidRequestError"
-                }
-              }
-            }
-          },
-          "401": {
-            "description": "UnauthorizedError",
-            "content": {
-              "application/json": {
-                "schema": {
-                  "$ref": "#/components/schemas/UnauthorizedError"
-                }
-              }
-            }
-          }
-        },
-        "description": "Run or resume the V1 to V2 session history migration and wait for completion.",
-        "summary": "Run V1 migration"
       }
     },
     "/api/websearch/provider": {
@@ -12134,6 +12097,94 @@
           "required": true
         }
       }
+    },
+    "/api/config": {
+      "get": {
+        "tags": [
+          "config"
+        ],
+        "operationId": "v2.config.get",
+        "parameters": [
+          {
+            "name": "location",
+            "in": "query",
+            "schema": {
+              "anyOf": [
+                {
+                  "type": "object",
+                  "properties": {
+                    "directory": {
+                      "anyOf": [
+                        {
+                          "type": "string"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    },
+                    "workspace": {
+                      "anyOf": [
+                        {
+                          "type": "string"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    }
+                  },
+                  "additionalProperties": false
+                },
+                {
+                  "type": "null"
+                }
+              ]
+            },
+            "required": false,
+            "style": "deepObject",
+            "explode": true
+          }
+        ],
+        "security": [],
+        "responses": {
+          "200": {
+            "description": "Success",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "type": "array",
+                  "items": {
+                    "$ref": "#/components/schemas/Config.Entry"
+                  }
+                }
+              }
+            }
+          },
+          "400": {
+            "description": "InvalidRequestError",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/InvalidRequestError"
+                }
+              }
+            }
+          },
+          "401": {
+            "description": "UnauthorizedError",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/UnauthorizedError"
+                }
+              }
+            }
+          }
+        },
+        "description": "Return configuration documents and discovery sources for the requested location, from lowest to highest priority.",
+        "summary": "Get configuration"
+      }
     }
   },
   "components": {
@@ -16014,7 +16065,10 @@
                     }
                   ]
                 }
-              }
+              },
+              "text": {
+                "type": "string"
+              }
             },
             "required": [
               "sessionID",
@@ -26457,120 +26511,1862 @@
           "results"
         ],
         "additionalProperties": false
-      }
-    },
-    "securitySchemes": {}
-  },
-  "security": [],
-  "tags": [
-    {
-      "name": "health"
-    },
-    {
-      "name": "server"
-    },
-    {
-      "name": "location"
-    },
-    {
-      "name": "agent"
-    },
-    {
-      "name": "plugin",
-      "description": "Experimental plugin routes."
-    },
-    {
-      "name": "session",
-      "description": "Experimental session routes."
-    },
-    {
-      "name": "session",
-      "description": "Experimental message routes."
-    },
-    {
-      "name": "model",
-      "description": "Experimental model routes."
-    },
-    {
-      "name": "generate",
-      "description": "Experimental one-shot generation routes."
-    },
-    {
-      "name": "provider",
-      "description": "Experimental provider routes."
-    },
-    {
-      "name": "integration",
-      "description": "Integration discovery and authentication routes."
-    },
-    {
-      "name": "mcp",
-      "description": "MCP server and resource routes."
-    },
-    {
-      "name": "credential"
-    },
-    {
-      "name": "project",
-      "description": "Location-scoped project routes."
-    },
-    {
-      "name": "form",
-      "description": "Session form routes."
-    },
-    {
-      "name": "permission",
-      "description": "Experimental permission routes."
-    },
-    {
-      "name": "filesystem",
-      "description": "Experimental location-scoped filesystem routes."
-    },
-    {
-      "name": "command",
-      "description": "Experimental command routes."
-    },
-    {
-      "name": "skill",
-      "description": "Experimental skill routes."
-    },
-    {
-      "name": "event",
-      "description": "Experimental event stream routes."
-    },
-    {
-      "name": "pty",
-      "description": "Experimental location-scoped PTY routes."
-    },
-    {
-      "name": "shell",
-      "description": "Experimental location-scoped shell command routes."
-    },
-    {
-      "name": "question",
-      "description": "Experimental session question routes."
-    },
-    {
-      "name": "reference",
-      "description": "Location-scoped project references."
-    },
-    {
-      "name": "projectCopy",
-      "description": "Project copy management routes."
-    },
-    {
-      "name": "vcs",
-      "description": "Location-scoped version control routes."
-    },
-    {
-      "name": "debug"
-    },
-    {
-      "name": "migration"
-    },
-    {
-      "name": "websearch",
-      "description": "Location-scoped web search routes."
+      },
+      "Config.ModelSelection": {
+        "anyOf": [
+          {
+            "type": "string",
+            "allOf": [
+              {
+                "pattern": "^[^/#]+\\/[^#]+(?:#[^#]+)?$"
+              }
+            ]
+          },
+          {
+            "type": "object",
+            "properties": {
+              "providerID": {
+                "type": "string",
+                "allOf": [
+                  {
+                    "pattern": "^[^/#]+$"
+                  }
+                ]
+              },
+              "model": {
+                "type": "string",
+                "allOf": [
+                  {
+                    "pattern": "^[^#]+$"
+                  }
+                ]
+              },
+              "variant": {
+                "anyOf": [
+                  {
+                    "type": "string",
+                    "allOf": [
+                      {
+                        "pattern": "^[^#]+$"
+                      }
+                    ]
+                  },
+                  {
+                    "type": "null"
+                  }
+                ]
+              }
+            },
+            "required": [
+              "providerID",
+              "model"
+            ],
+            "additionalProperties": false
+          }
+        ]
+      },
+      "Config.Provider.Request": {
+        "type": "object",
+        "properties": {
+          "headers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "body": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Agent": {
+        "type": "object",
+        "properties": {
+          "model": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ModelSelection"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "request": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Provider.Request"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "system": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "mode": {
+            "anyOf": [
+              {
+                "type": "string",
+                "enum": [
+                  "subagent",
+                  "primary",
+                  "all"
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "hidden": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "color": {
+            "anyOf": [
+              {
+                "type": "string",
+                "allOf": [
+                  {
+                    "pattern": "^#[0-9a-fA-F]{6}$"
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "steps": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "permissions": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Permission.Ruleset"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Watcher": {
+        "type": "object",
+        "properties": {
+          "ignore": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Formatter.Entry": {
+        "type": "object",
+        "properties": {
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "command": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "environment": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "extensions": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.LSP.Server": {
+        "type": "object",
+        "properties": {
+          "command": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            }
+          },
+          "extensions": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "env": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "initialization": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "command"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Media.Image": {
+        "type": "object",
+        "properties": {
+          "auto_resize": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_width": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_height": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_base64_bytes": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Media": {
+        "type": "object",
+        "properties": {
+          "image": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Media.Image"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.ToolOutput": {
+        "type": "object",
+        "properties": {
+          "max_lines": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "max_bytes": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "exclusiveMinimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.MCP": {
+        "type": "object",
+        "properties": {
+          "timeout": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Mcp.TimeoutConfig"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "servers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "anyOf": [
+                    {
+                      "$ref": "#/components/schemas/Mcp.LocalConfig"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Mcp.RemoteConfig"
+                    }
+                  ]
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Compaction.Keep": {
+        "type": "object",
+        "properties": {
+          "tokens": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "minimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Compaction": {
+        "type": "object",
+        "properties": {
+          "auto": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "keep": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Compaction.Keep"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "buffer": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "minimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Command": {
+        "type": "object",
+        "properties": {
+          "template": {
+            "type": "string"
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "agent": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "model": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ModelSelection"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "subtask": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "template"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Reference.Git": {
+        "type": "object",
+        "properties": {
+          "repository": {
+            "type": "string"
+          },
+          "branch": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "hidden": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "repository"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Reference.Local": {
+        "type": "object",
+        "properties": {
+          "path": {
+            "type": "string"
+          },
+          "description": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "hidden": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "ConfigWebSearch.Info": {
+        "type": "object",
+        "properties": {
+          "provider": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "provider"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Plugin.Entry": {
+        "type": "object",
+        "properties": {
+          "package": {
+            "type": "string"
+          },
+          "options": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "package"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Warming": {
+        "type": "object",
+        "properties": {
+          "prompt": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Prompt sent for keep-alive requests"
+          },
+          "interval": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Idle time between keep-alive requests (default: \"4 minutes\")"
+          },
+          "duration": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Time after the last active request to keep a session warm (default: \"30 minutes\")"
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Model.Cost.Cache": {
+        "type": "object",
+        "properties": {
+          "read": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "write": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Model.Cost": {
+        "type": "object",
+        "properties": {
+          "tier": {
+            "anyOf": [
+              {
+                "type": "object",
+                "properties": {
+                  "type": {
+                    "type": "string",
+                    "enum": [
+                      "context"
+                    ]
+                  },
+                  "size": {
+                    "type": "integer"
+                  }
+                },
+                "required": [
+                  "type",
+                  "size"
+                ],
+                "additionalProperties": false
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "input": {
+            "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+          },
+          "output": {
+            "$ref": "#/components/schemas/Money.USDPerMillionTokens"
+          },
+          "cache": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Model.Cost.Cache"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "required": [
+          "input",
+          "output"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Model.Limit": {
+        "type": "object",
+        "properties": {
+          "context": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "input": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "output": {
+            "anyOf": [
+              {
+                "type": "integer"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Model": {
+        "type": "object",
+        "properties": {
+          "modelID": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "family": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "name": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "compatibility": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Model.Compatibility"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "package": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "settings": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "headers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "body": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "capabilities": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Model.Capabilities"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "variants": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "object",
+                  "properties": {
+                    "id": {
+                      "type": "string"
+                    },
+                    "settings": {
+                      "anyOf": [
+                        {
+                          "type": "object"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    },
+                    "headers": {
+                      "anyOf": [
+                        {
+                          "type": "object",
+                          "additionalProperties": {
+                            "type": "string"
+                          }
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    },
+                    "body": {
+                      "anyOf": [
+                        {
+                          "type": "object"
+                        },
+                        {
+                          "type": "null"
+                        }
+                      ]
+                    }
+                  },
+                  "required": [
+                    "id"
+                  ],
+                  "additionalProperties": false
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "cost": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "$ref": "#/components/schemas/Config.Model.Cost"
+                  },
+                  {
+                    "type": "array",
+                    "items": {
+                      "$ref": "#/components/schemas/Config.Model.Cost"
+                    }
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "disabled": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "limit": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Model.Limit"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Provider": {
+        "type": "object",
+        "properties": {
+          "name": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "env": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "package": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "settings": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "headers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "body": {
+            "anyOf": [
+              {
+                "type": "object"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "models": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Model"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "ConfigExperimental.Info": {
+        "type": "object",
+        "properties": {
+          "subagent_depth": {
+            "anyOf": [
+              {
+                "type": "integer",
+                "allOf": [
+                  {
+                    "minimum": 0
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Maximum subagent nesting depth. Defaults to 1."
+          },
+          "policies": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "object",
+                  "properties": {
+                    "action": {
+                      "type": "string",
+                      "enum": [
+                        "provider.use"
+                      ]
+                    },
+                    "resource": {
+                      "type": "string"
+                    },
+                    "effect": {
+                      "type": "string",
+                      "enum": [
+                        "allow",
+                        "deny"
+                      ]
+                    }
+                  },
+                  "required": [
+                    "action",
+                    "resource",
+                    "effect"
+                  ],
+                  "additionalProperties": false
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Ordered policies controlling access to configured resources"
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Info": {
+        "type": "object",
+        "properties": {
+          "$schema": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "JSON schema reference for configuration validation"
+          },
+          "shell": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Default shell to use for terminal and shell tool execution"
+          },
+          "model": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ModelSelection"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Default model to use when no session or agent model is selected"
+          },
+          "default_agent": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Default primary agent to use when no session agent is selected"
+          },
+          "autoupdate": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "type": "string",
+                    "enum": [
+                      "notify"
+                    ]
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Automatically update or notify when a new version is available"
+          },
+          "share": {
+            "anyOf": [
+              {
+                "type": "string",
+                "enum": [
+                  "manual",
+                  "auto",
+                  "disabled"
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Control whether sessions may be shared manually, automatically, or not at all"
+          },
+          "enterprise": {
+            "anyOf": [
+              {
+                "type": "object",
+                "properties": {
+                  "url": {
+                    "anyOf": [
+                      {
+                        "type": "string"
+                      },
+                      {
+                        "type": "null"
+                      }
+                    ]
+                  }
+                },
+                "additionalProperties": false
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enterprise sharing service configuration"
+          },
+          "username": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Username displayed in conversations and used for telemetry identity"
+          },
+          "permissions": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Permission.Ruleset"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Ordered tool permission rules applied to agent tool use"
+          },
+          "agents": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Agent"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Named built-in agent overrides and custom agent definitions"
+          },
+          "snapshots": {
+            "anyOf": [
+              {
+                "type": "boolean"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enable snapshots used for undo and revert behavior"
+          },
+          "watcher": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Watcher"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Filesystem watcher configuration"
+          },
+          "formatter": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "type": "object",
+                    "additionalProperties": {
+                      "$ref": "#/components/schemas/Config.Formatter.Entry"
+                    }
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enable built-in formatters or configure formatter overrides"
+          },
+          "lsp": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "type": "object",
+                    "additionalProperties": {
+                      "anyOf": [
+                        {
+                          "type": "object",
+                          "properties": {
+                            "disabled": {
+                              "type": "boolean",
+                              "enum": [
+                                true
+                              ]
+                            }
+                          },
+                          "required": [
+                            "disabled"
+                          ],
+                          "additionalProperties": false
+                        },
+                        {
+                          "$ref": "#/components/schemas/Config.LSP.Server"
+                        }
+                      ]
+                    }
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Enable built-in language servers or configure server overrides"
+          },
+          "media": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Media"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Media processing configuration"
+          },
+          "tool_output": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.ToolOutput"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Tool output truncation thresholds"
+          },
+          "mcp": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.MCP"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "MCP server configuration"
+          },
+          "compaction": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/Config.Compaction"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Conversation compaction behavior"
+          },
+          "skills": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Additional paths or URLs to discover skills from"
+          },
+          "commands": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Command"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Named slash command definitions"
+          },
+          "instructions": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Additional paths or URLs supplying ambient instructions"
+          },
+          "references": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "anyOf": [
+                    {
+                      "type": "string"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Config.Reference.Git"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Config.Reference.Local"
+                    }
+                  ]
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Named local directories or Git repositories available as external context"
+          },
+          "websearch": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/ConfigWebSearch.Info"
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Web search provider selection"
+          },
+          "plugins": {
+            "anyOf": [
+              {
+                "type": "array",
+                "items": {
+                  "anyOf": [
+                    {
+                      "type": "string"
+                    },
+                    {
+                      "$ref": "#/components/schemas/Config.Plugin.Entry"
+                    }
+                  ]
+                }
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Ordered plugin enablement directives and external package declarations"
+          },
+          "warming": {
+            "anyOf": [
+              {
+                "anyOf": [
+                  {
+                    "type": "boolean"
+                  },
+                  {
+                    "$ref": "#/components/schemas/Config.Warming"
+                  }
+                ]
+              },
+              {
+                "type": "null"
+              }
+            ],
+            "description": "Keep recently active sessions warm with transient model requests (default: false)"
+          },
+          "providers": {
+            "anyOf": [
+              {
+                "type": "object",
+                "additionalProperties": {
+                  "$ref": "#/components/schemas/Config.Provider"
+                }
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "experimental": {
+            "anyOf": [
+              {
+                "$ref": "#/components/schemas/ConfigExperimental.Info"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          }
+        },
+        "additionalProperties": false
+      },
+      "Config.Document": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "document"
+            ]
+          },
+          "path": {
+            "anyOf": [
+              {
+                "type": "string"
+              },
+              {
+                "type": "null"
+              }
+            ]
+          },
+          "info": {
+            "$ref": "#/components/schemas/Config.Info"
+          }
+        },
+        "required": [
+          "type",
+          "info"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Directory": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "directory"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.File": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "file"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.AgentsDirectory": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "agents"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.ClaudeDirectory": {
+        "type": "object",
+        "properties": {
+          "type": {
+            "type": "string",
+            "enum": [
+              "claude"
+            ]
+          },
+          "path": {
+            "type": "string"
+          }
+        },
+        "required": [
+          "type",
+          "path"
+        ],
+        "additionalProperties": false
+      },
+      "Config.Entry": {
+        "anyOf": [
+          {
+            "$ref": "#/components/schemas/Config.Document"
+          },
+          {
+            "$ref": "#/components/schemas/Config.Directory"
+          },
+          {
+            "$ref": "#/components/schemas/Config.File"
+          },
+          {
+            "$ref": "#/components/schemas/Config.AgentsDirectory"
+          },
+          {
+            "$ref": "#/components/schemas/Config.ClaudeDirectory"
+          }
+        ]
+      }
+    },
+    "securitySchemes": {}
+  },
+  "security": [],
+  "tags": [
+    {
+      "name": "health"
+    },
+    {
+      "name": "server"
+    },
+    {
+      "name": "location"
+    },
+    {
+      "name": "agent"
+    },
+    {
+      "name": "plugin",
+      "description": "Experimental plugin routes."
+    },
+    {
+      "name": "session",
+      "description": "Experimental session routes."
+    },
+    {
+      "name": "session",
+      "description": "Experimental message routes."
+    },
+    {
+      "name": "model",
+      "description": "Experimental model routes."
+    },
+    {
+      "name": "generate",
+      "description": "Experimental one-shot generation routes."
+    },
+    {
+      "name": "provider",
+      "description": "Experimental provider routes."
+    },
+    {
+      "name": "integration",
+      "description": "Integration discovery and authentication routes."
+    },
+    {
+      "name": "mcp",
+      "description": "MCP server and resource routes."
+    },
+    {
+      "name": "credential"
+    },
+    {
+      "name": "project",
+      "description": "Location-scoped project routes."
+    },
+    {
+      "name": "form",
+      "description": "Session form routes."
+    },
+    {
+      "name": "permission",
+      "description": "Experimental permission routes."
+    },
+    {
+      "name": "filesystem",
+      "description": "Experimental location-scoped filesystem routes."
+    },
+    {
+      "name": "command",
+      "description": "Experimental command routes."
+    },
+    {
+      "name": "skill",
+      "description": "Experimental skill routes."
+    },
+    {
+      "name": "event",
+      "description": "Experimental event stream routes."
+    },
+    {
+      "name": "pty",
+      "description": "Experimental location-scoped PTY routes."
+    },
+    {
+      "name": "shell",
+      "description": "Experimental location-scoped shell command routes."
+    },
+    {
+      "name": "question",
+      "description": "Experimental session question routes."
+    },
+    {
+      "name": "reference",
+      "description": "Location-scoped project references."
+    },
+    {
+      "name": "projectCopy",
+      "description": "Project copy management routes."
+    },
+    {
+      "name": "vcs",
+      "description": "Location-scoped version control routes."
+    },
+    {
+      "name": "debug"
+    },
+    {
+      "name": "migration"
+    },
+    {
+      "name": "websearch",
+      "description": "Location-scoped web search routes."
+    },
+    {
+      "name": "config",
+      "description": "Location-scoped configuration routes."
     }
   ]
 }