From ef9d18b88b8bed999df6187390ce9f2444783f48 Mon Sep 17 00:00:00 2001 From: spencer-hong Date: Fri, 20 Feb 2026 12:10:12 -0500 Subject: [PATCH 1/6] feat: non-interactive fix; yolo mode; kimi fix --- packages/opencode/src/config/config.ts | 3 + packages/opencode/src/flag/flag.ts | 1 + packages/opencode/src/project/bootstrap.ts | 3 + packages/opencode/src/provider/provider.ts | 23 +++++ .../src/server/routes/instance/config.ts | 96 +++++++++++++++++++ packages/opencode/src/yolo/index.ts | 54 +++++++++++ 6 files changed, 180 insertions(+) create mode 100644 packages/opencode/src/yolo/index.ts diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 55684fc70dfb..54a2c2b532c1 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -196,6 +196,9 @@ const InfoSchema = Schema.Struct({ url: Schema.optional(Schema.String).annotate({ description: "Enterprise URL" }), }), ), + yolo: Schema.optional(Schema.Boolean).annotate({ + description: "Enable YOLO mode - auto-approve all permission prompts (except explicit deny rules)", + }), compaction: Schema.optional( Schema.Struct({ auto: Schema.optional(Schema.Boolean).annotate({ diff --git a/packages/opencode/src/flag/flag.ts b/packages/opencode/src/flag/flag.ts index 72c8931f5b71..5222dc0de233 100644 --- a/packages/opencode/src/flag/flag.ts +++ b/packages/opencode/src/flag/flag.ts @@ -27,6 +27,7 @@ export const Flag = { OTEL_EXPORTER_OTLP_ENDPOINT: process.env["OTEL_EXPORTER_OTLP_ENDPOINT"], OTEL_EXPORTER_OTLP_HEADERS: process.env["OTEL_EXPORTER_OTLP_HEADERS"], + OPENCODE_YOLO: truthy("OPENCODE_YOLO"), OPENCODE_AUTO_SHARE: truthy("OPENCODE_AUTO_SHARE"), OPENCODE_AUTO_HEAP_SNAPSHOT: truthy("OPENCODE_AUTO_HEAP_SNAPSHOT"), OPENCODE_GIT_BASH_PATH: process.env["OPENCODE_GIT_BASH_PATH"], diff --git a/packages/opencode/src/project/bootstrap.ts b/packages/opencode/src/project/bootstrap.ts index a7c071a9f80b..ea9b1c0fc5dc 100644 --- a/packages/opencode/src/project/bootstrap.ts +++ b/packages/opencode/src/project/bootstrap.ts @@ -13,11 +13,14 @@ import { FileWatcher } from "@/file/watcher" import { ShareNext } from "@/share" import * as Effect from "effect/Effect" import { Config } from "@/config" +import { Yolo } from "../yolo" export const InstanceBootstrap = Effect.gen(function* () { Log.Default.info("bootstrapping", { directory: Instance.directory }) // everything depends on config so eager load it for nice traces yield* Config.Service.use((svc) => svc.get()) + // Yolo depends on config so init it right after config is ready. + yield* Effect.promise(() => Yolo.init()) // Plugin can mutate config so it has to be initialized before anything else. yield* Plugin.Service.use((svc) => svc.init()) yield* Effect.all( diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index d643f25373af..a088feaca6fb 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -1472,6 +1472,29 @@ const layer: Layer.Layer< } } + // Kimi's coding API requires a thinking block on every assistant message + // that contains tool_use when thinking is enabled. The @ai-sdk/anthropic SDK + // drops thinking blocks from multi-turn messages because Kimi doesn't return + // Anthropic-style signatures. We inject an empty thinking block here so Kimi + // doesn't reject the request with 'reasoning_content is missing'. + if (model.providerID === "kimi-for-coding" && opts.body && opts.method === "POST") { + const body = JSON.parse(opts.body as string) + if (Array.isArray(body.messages)) { + for (const msg of body.messages) { + if (msg.role !== "assistant" || !Array.isArray(msg.content)) continue + const hasToolUse = msg.content.some((b: any) => b.type === "tool_use") + const hasThinking = msg.content.some( + (b: any) => b.type === "thinking" || b.type === "redacted_thinking", + ) + if (hasToolUse && !hasThinking) { + msg.content.unshift({ type: "thinking", thinking: ".", signature: "placeholder" }) + msg.reasoning_content = "." + } + } + opts.body = JSON.stringify(body) + } + } + const res = await fetchFn(input, { ...opts, // @ts-ignore see here: https://github.com/oven-sh/bun/issues/16682 diff --git a/packages/opencode/src/server/routes/instance/config.ts b/packages/opencode/src/server/routes/instance/config.ts index 7f368cd31c22..1b4f394e43b2 100644 --- a/packages/opencode/src/server/routes/instance/config.ts +++ b/packages/opencode/src/server/routes/instance/config.ts @@ -1,12 +1,34 @@ import { Hono } from "hono" import { describeRoute, validator, resolver } from "hono-openapi" import z from "zod" +import path from "path" import { Config } from "@/config" import { Provider } from "@/provider" +import { Yolo } from "@/yolo" +import { Global } from "@/global" import { errors } from "../../error" +import { Log } from "@/util/log" import { lazy } from "@/util/lazy" import { jsonRequest } from "./trace" +const log = Log.create({ service: "server" }) + +// Helper to read/write global config for YOLO persistence (uses config.json, not opencode.jsonc) +async function readGlobalConfig(): Promise> { + const filepath = path.join(Global.Path.config, "config.json") + try { + const text = await Bun.file(filepath).text() + return JSON.parse(text) + } catch { + return {} + } +} + +async function writeGlobalConfig(config: Record): Promise { + const filepath = path.join(Global.Path.config, "config.json") + await Bun.write(filepath, JSON.stringify(config, null, 2)) +} + export const ConfigRoutes = lazy(() => new Hono() .get( @@ -85,5 +107,79 @@ export const ConfigRoutes = lazy(() => default: Provider.defaultModelIDs(providers), } }), + ) + .get( + "/yolo", + describeRoute({ + summary: "Get YOLO mode status", + description: + "Check if YOLO mode is enabled. When enabled, all permission prompts are auto-approved (except explicit deny rules).", + operationId: "config.yolo.get", + responses: { + 200: { + description: "YOLO mode status", + content: { + "application/json": { + schema: resolver(z.object({ enabled: z.boolean(), persisted: z.boolean() })), + }, + }, + }, + }, + }), + async (c) => { + const globalConfig = await readGlobalConfig() + return c.json({ + enabled: Yolo.isEnabled(), + persisted: globalConfig.yolo === true, + }) + }, + ) + .post( + "/yolo", + describeRoute({ + summary: "Set YOLO mode", + description: + "Enable or disable YOLO mode. When enabled, all permission prompts are auto-approved (except explicit deny rules). Use with caution. Set persist=true to save to config file.", + operationId: "config.yolo.set", + responses: { + 200: { + description: "YOLO mode updated", + content: { + "application/json": { + schema: resolver(z.object({ enabled: z.boolean(), persisted: z.boolean() })), + }, + }, + }, + }, + }), + validator("json", z.object({ enabled: z.boolean(), persist: z.boolean().optional() })), + async (c) => { + const { enabled, persist } = c.req.valid("json") + Yolo.set(enabled) + + try { + const globalConfig = await readGlobalConfig() + const wasPersisted = globalConfig.yolo === true + + if (persist) { + if (enabled) { + globalConfig.yolo = true + } else { + delete globalConfig.yolo + } + await writeGlobalConfig(globalConfig) + log.info("YOLO mode config updated", { enabled, path: Global.Path.config }) + } else if (wasPersisted && enabled) { + delete globalConfig.yolo + await writeGlobalConfig(globalConfig) + log.info("YOLO mode downgraded to session-only", { path: Global.Path.config }) + } + } catch (e) { + log.error("Failed to update YOLO config", { error: e }) + } + + const finalConfig = await readGlobalConfig() + return c.json({ enabled: Yolo.isEnabled(), persisted: finalConfig.yolo === true }) + }, ), ) diff --git a/packages/opencode/src/yolo/index.ts b/packages/opencode/src/yolo/index.ts new file mode 100644 index 000000000000..b36e809265df --- /dev/null +++ b/packages/opencode/src/yolo/index.ts @@ -0,0 +1,54 @@ +import { Bus } from "@/bus" +import { BusEvent } from "@/bus/bus-event" +import { Config } from "@/config/config" +import { Flag } from "@/flag/flag" +import { Log } from "@/util/log" +import z from "zod" + +export namespace Yolo { + const log = Log.create({ service: "yolo" }) + + let enabled = Flag.OPENCODE_YOLO + + export const Event = { + Changed: BusEvent.define( + "yolo.changed", + z.object({ + enabled: z.boolean(), + }), + ), + } + + export async function init() { + const config = await Config.global() + if (config.yolo === true) { + enabled = true + log.warn("YOLO mode enabled via config") + } + if (Flag.OPENCODE_YOLO) { + enabled = true + log.warn("YOLO mode enabled via OPENCODE_YOLO env var") + } + if (enabled) { + log.warn("YOLO mode is ACTIVE - all permission prompts will be auto-approved") + } + } + + export function isEnabled(): boolean { + return enabled + } + + export function set(value: boolean) { + const previous = enabled + enabled = value + if (previous !== value) { + log.warn(`YOLO mode ${value ? "ENABLED" : "DISABLED"}`) + Bus.publish(Event.Changed, { enabled: value }) + } + } + + export function toggle(): boolean { + set(!enabled) + return enabled + } +} From dced8c58161f0753477bf3cb0af078d4913094bb Mon Sep 17 00:00:00 2001 From: spencer-hong Date: Tue, 31 Mar 2026 13:30:44 -0400 Subject: [PATCH 2/6] fix: use Config.getGlobal() instead of removed Config.global() Config.global() was renamed to Config.getGlobal() in upstream. The Yolo.init() call in bootstrap crashed with "Config.global is not a function" on session creation. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/opencode/src/yolo/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/yolo/index.ts b/packages/opencode/src/yolo/index.ts index b36e809265df..5a2c61353b67 100644 --- a/packages/opencode/src/yolo/index.ts +++ b/packages/opencode/src/yolo/index.ts @@ -20,7 +20,7 @@ export namespace Yolo { } export async function init() { - const config = await Config.global() + const config = await Config.getGlobal() if (config.yolo === true) { enabled = true log.warn("YOLO mode enabled via config") From 5c74d8e16e4f040818bd4339c90738e42788df01 Mon Sep 17 00:00:00 2001 From: spencer-hong Date: Tue, 31 Mar 2026 13:59:07 -0400 Subject: [PATCH 3/6] fix(permission): wire yolo mode end to end --- packages/opencode/src/flag/flag.ts | 4 +- packages/opencode/src/index.ts | 7 ++ packages/opencode/src/permission/index.ts | 10 +++ packages/opencode/src/yolo/index.ts | 21 ++++- .../opencode/test/permission/next.test.ts | 65 ++++++++++++++++ packages/sdk/js/src/v2/gen/sdk.gen.ts | 78 +++++++++++++++++++ 6 files changed, 180 insertions(+), 5 deletions(-) diff --git a/packages/opencode/src/flag/flag.ts b/packages/opencode/src/flag/flag.ts index 5222dc0de233..1a23fbbe4b3c 100644 --- a/packages/opencode/src/flag/flag.ts +++ b/packages/opencode/src/flag/flag.ts @@ -27,7 +27,6 @@ export const Flag = { OTEL_EXPORTER_OTLP_ENDPOINT: process.env["OTEL_EXPORTER_OTLP_ENDPOINT"], OTEL_EXPORTER_OTLP_HEADERS: process.env["OTEL_EXPORTER_OTLP_HEADERS"], - OPENCODE_YOLO: truthy("OPENCODE_YOLO"), OPENCODE_AUTO_SHARE: truthy("OPENCODE_AUTO_SHARE"), OPENCODE_AUTO_HEAP_SNAPSHOT: truthy("OPENCODE_AUTO_HEAP_SNAPSHOT"), OPENCODE_GIT_BASH_PATH: process.env["OPENCODE_GIT_BASH_PATH"], @@ -90,6 +89,9 @@ export const Flag = { get OPENCODE_DISABLE_PROJECT_CONFIG() { return truthy("OPENCODE_DISABLE_PROJECT_CONFIG") }, + get OPENCODE_YOLO() { + return truthy("OPENCODE_YOLO") + }, get OPENCODE_TUI_CONFIG() { return process.env["OPENCODE_TUI_CONFIG"] }, diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts index 0a3a927b46ed..5c86b72e58d1 100644 --- a/packages/opencode/src/index.ts +++ b/packages/opencode/src/index.ts @@ -87,10 +87,17 @@ const cli = yargs(args) describe: "run without external plugins", type: "boolean", }) + .option("yolo", { + describe: "auto-approve ask permission prompts", + type: "boolean", + }) .middleware(async (opts) => { if (opts.pure) { process.env.OPENCODE_PURE = "1" } + if (opts.yolo) { + process.env.OPENCODE_YOLO = "1" + } await Log.init({ print: process.argv.includes("--print-logs"), diff --git a/packages/opencode/src/permission/index.ts b/packages/opencode/src/permission/index.ts index b9a221155c9f..044333b7d7b8 100644 --- a/packages/opencode/src/permission/index.ts +++ b/packages/opencode/src/permission/index.ts @@ -10,6 +10,7 @@ import { zod } from "@/util/effect-zod" import { Log } from "@/util" import { withStatics } from "@/util/schema" import { Wildcard } from "@/util" +import { Yolo } from "@/yolo" import { Deferred, Effect, Layer, Schema, Context } from "effect" import os from "os" import { evaluate as evalRule } from "./evaluate" @@ -180,7 +181,9 @@ export const layer = Layer.effect( const ask = Effect.fn("Permission.ask")(function* (input: AskInput) { const { approved, pending } = yield* InstanceState.get(state) const { ruleset, ...request } = input + const yolo = Yolo.isEnabled() let needsAsk = false + let auto = false for (const pattern of request.patterns) { const rule = evaluate(request.permission, pattern, ruleset, approved) @@ -191,9 +194,16 @@ export const layer = Layer.effect( }) } if (rule.action === "allow") continue + if (yolo) { + auto = true + continue + } needsAsk = true } + if (auto) { + log.warn("auto-approved by yolo", { permission: request.permission, patterns: request.patterns }) + } if (!needsAsk) return const id = request.id ?? PermissionID.ascending() diff --git a/packages/opencode/src/yolo/index.ts b/packages/opencode/src/yolo/index.ts index 5a2c61353b67..8dd9ad29fb0e 100644 --- a/packages/opencode/src/yolo/index.ts +++ b/packages/opencode/src/yolo/index.ts @@ -1,7 +1,8 @@ +import path from "path" import { Bus } from "@/bus" import { BusEvent } from "@/bus/bus-event" -import { Config } from "@/config/config" import { Flag } from "@/flag/flag" +import { Global } from "@/global" import { Log } from "@/util/log" import z from "zod" @@ -19,9 +20,19 @@ export namespace Yolo { ), } + async function readGlobalYolo(): Promise { + const filepath = path.join(Global.Path.config, "config.json") + try { + const text = await Bun.file(filepath).text() + const parsed = JSON.parse(text) + return parsed?.yolo === true + } catch { + return false + } + } + export async function init() { - const config = await Config.getGlobal() - if (config.yolo === true) { + if (await readGlobalYolo()) { enabled = true log.warn("YOLO mode enabled via config") } @@ -43,7 +54,9 @@ export namespace Yolo { enabled = value if (previous !== value) { log.warn(`YOLO mode ${value ? "ENABLED" : "DISABLED"}`) - Bus.publish(Event.Changed, { enabled: value }) + void Bus.publish(Event.Changed, { enabled: value }).catch((err) => { + log.debug("failed to publish yolo.changed", { err: String(err) }) + }) } } diff --git a/packages/opencode/test/permission/next.test.ts b/packages/opencode/test/permission/next.test.ts index d654d4b876b8..8c3d78c94e61 100644 --- a/packages/opencode/test/permission/next.test.ts +++ b/packages/opencode/test/permission/next.test.ts @@ -9,6 +9,7 @@ import { Instance } from "../../src/project/instance" import { provideInstance, provideTmpdirInstance, tmpdirScoped } from "../fixture/fixture" import { testEffect } from "../lib/effect" import { MessageID, SessionID } from "../../src/session/schema" +import { Yolo } from "../../src/yolo" const bus = Bus.layer const env = Layer.mergeAll(Permission.layer.pipe(Layer.provide(bus)), bus, CrossSpawnSpawner.defaultLayer) @@ -1078,3 +1079,67 @@ it.live("ask - abort should clear pending request", () => if (Exit.isFailure(exit)) expect(Cause.squash(exit.cause)).toBeInstanceOf(Permission.RejectedError) }), ) + +it.live("ask - auto-approves ask when yolo is enabled", () => + Effect.gen(function* () { + const dir = yield* tmpdirScoped({ git: true }) + const run = withProvided(dir) + + const previous = Yolo.isEnabled() + Yolo.set(true) + try { + const result = yield* ask({ + sessionID: SessionID.make("session_test"), + permission: "bash", + patterns: ["ls"], + metadata: {}, + always: [], + ruleset: [{ permission: "bash", pattern: "*", action: "ask" }], + }).pipe(run) + expect(result).toBeUndefined() + expect(yield* list().pipe(run)).toHaveLength(0) + } finally { + Yolo.set(previous) + } + }), +) + +it.live("ask - yolo still respects deny rules", () => + Effect.gen(function* () { + const dir = yield* tmpdirScoped({ git: true }) + const run = withProvided(dir) + + const previous = Yolo.isEnabled() + Yolo.set(true) + try { + const err = yield* fail( + ask({ + sessionID: SessionID.make("session_test"), + permission: "bash", + patterns: ["rm -rf /"], + metadata: {}, + always: [], + ruleset: [{ permission: "bash", pattern: "*", action: "deny" }], + }).pipe(run), + ) + expect(err).toBeInstanceOf(Permission.DeniedError) + } finally { + Yolo.set(previous) + } + }), +) + +test("yolo - init reads OPENCODE_YOLO at runtime", async () => { + const previous = Yolo.isEnabled() + const prevEnv = process.env.OPENCODE_YOLO + Yolo.set(false) + process.env.OPENCODE_YOLO = "1" + try { + await Yolo.init() + expect(Yolo.isEnabled()).toBe(true) + } finally { + Yolo.set(previous) + if (prevEnv === undefined) delete process.env.OPENCODE_YOLO + else process.env.OPENCODE_YOLO = prevEnv + } +}) diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index 6248eb8e4d64..036a4190b73e 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -19,6 +19,8 @@ import type { ConfigProvidersResponses, ConfigUpdateErrors, ConfigUpdateResponses, + ConfigYoloGetResponses, + ConfigYoloSetResponses, EventSubscribeResponses, EventTuiCommandExecute, EventTuiPromptAppend, @@ -1298,6 +1300,77 @@ export class Pty extends HeyApiClient { } } +export class Yolo extends HeyApiClient { + /** + * Get YOLO mode status + * + * Check if YOLO mode is enabled. When enabled, all permission prompts are auto-approved (except explicit deny rules). + */ + public get( + parameters?: { + directory?: string + workspace?: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get({ + url: "/config/yolo", + ...options, + ...params, + }) + } + + /** + * Set YOLO mode + * + * Enable or disable YOLO mode. When enabled, all permission prompts are auto-approved (except explicit deny rules). Use with caution. Set persist=true to save to config file. + */ + public set( + parameters?: { + directory?: string + workspace?: string + enabled?: boolean + persist?: boolean + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "query", key: "directory" }, + { in: "query", key: "workspace" }, + { in: "body", key: "enabled" }, + { in: "body", key: "persist" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post({ + url: "/config/yolo", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } +} + export class Config2 extends HeyApiClient { /** * Get configuration @@ -1395,6 +1468,11 @@ export class Config2 extends HeyApiClient { ...params, }) } + + private _yolo?: Yolo + get yolo(): Yolo { + return (this._yolo ??= new Yolo({ client: this.client })) + } } export class Tool extends HeyApiClient { From 580cd58d57303dbd69d8862b26ed6551c5727cfc Mon Sep 17 00:00:00 2001 From: spencer-hong Date: Tue, 21 Apr 2026 11:03:00 -0400 Subject: [PATCH 4/6] chore: drop stale yolo SDK bindings from sdk.gen.ts (regenerate) Generated file was carrying over yolo client code from our fork, but the matching type exports live in types.gen.ts which we took from upstream. Take upstream's sdk.gen.ts verbatim; the yolo HTTP routes still exist server-side and SDK bindings can be regenerated. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/sdk/js/src/v2/gen/sdk.gen.ts | 78 --------------------------- 1 file changed, 78 deletions(-) diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index 036a4190b73e..6248eb8e4d64 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -19,8 +19,6 @@ import type { ConfigProvidersResponses, ConfigUpdateErrors, ConfigUpdateResponses, - ConfigYoloGetResponses, - ConfigYoloSetResponses, EventSubscribeResponses, EventTuiCommandExecute, EventTuiPromptAppend, @@ -1300,77 +1298,6 @@ export class Pty extends HeyApiClient { } } -export class Yolo extends HeyApiClient { - /** - * Get YOLO mode status - * - * Check if YOLO mode is enabled. When enabled, all permission prompts are auto-approved (except explicit deny rules). - */ - public get( - parameters?: { - directory?: string - workspace?: string - }, - options?: Options, - ) { - const params = buildClientParams( - [parameters], - [ - { - args: [ - { in: "query", key: "directory" }, - { in: "query", key: "workspace" }, - ], - }, - ], - ) - return (options?.client ?? this.client).get({ - url: "/config/yolo", - ...options, - ...params, - }) - } - - /** - * Set YOLO mode - * - * Enable or disable YOLO mode. When enabled, all permission prompts are auto-approved (except explicit deny rules). Use with caution. Set persist=true to save to config file. - */ - public set( - parameters?: { - directory?: string - workspace?: string - enabled?: boolean - persist?: boolean - }, - options?: Options, - ) { - const params = buildClientParams( - [parameters], - [ - { - args: [ - { in: "query", key: "directory" }, - { in: "query", key: "workspace" }, - { in: "body", key: "enabled" }, - { in: "body", key: "persist" }, - ], - }, - ], - ) - return (options?.client ?? this.client).post({ - url: "/config/yolo", - ...options, - ...params, - headers: { - "Content-Type": "application/json", - ...options?.headers, - ...params.headers, - }, - }) - } -} - export class Config2 extends HeyApiClient { /** * Get configuration @@ -1468,11 +1395,6 @@ export class Config2 extends HeyApiClient { ...params, }) } - - private _yolo?: Yolo - get yolo(): Yolo { - return (this._yolo ??= new Yolo({ client: this.client })) - } } export class Tool extends HeyApiClient { From 90685ddae1a06ce8eda1c4afa5893cd3612649cb Mon Sep 17 00:00:00 2001 From: spencer-hong Date: Tue, 21 Apr 2026 11:03:57 -0400 Subject: [PATCH 5/6] fix: correct Log import path for yolo/config routes @/util/log is re-exported as a namespace from @/util; importing Log directly from @/util/log fails after upstream's util reorg. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/opencode/src/server/routes/instance/config.ts | 2 +- packages/opencode/src/yolo/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/opencode/src/server/routes/instance/config.ts b/packages/opencode/src/server/routes/instance/config.ts index 1b4f394e43b2..6337aa0f7f4c 100644 --- a/packages/opencode/src/server/routes/instance/config.ts +++ b/packages/opencode/src/server/routes/instance/config.ts @@ -7,7 +7,7 @@ import { Provider } from "@/provider" import { Yolo } from "@/yolo" import { Global } from "@/global" import { errors } from "../../error" -import { Log } from "@/util/log" +import { Log } from "@/util" import { lazy } from "@/util/lazy" import { jsonRequest } from "./trace" diff --git a/packages/opencode/src/yolo/index.ts b/packages/opencode/src/yolo/index.ts index 8dd9ad29fb0e..612c6856ec73 100644 --- a/packages/opencode/src/yolo/index.ts +++ b/packages/opencode/src/yolo/index.ts @@ -3,7 +3,7 @@ import { Bus } from "@/bus" import { BusEvent } from "@/bus/bus-event" import { Flag } from "@/flag/flag" import { Global } from "@/global" -import { Log } from "@/util/log" +import { Log } from "@/util" import z from "zod" export namespace Yolo { From 8fa4bbfbd82581499a5bc97b58ec72d4f8c53b78 Mon Sep 17 00:00:00 2001 From: spencer-hong Date: Wed, 22 Apr 2026 16:29:55 -0400 Subject: [PATCH 6/6] Hide TUI sidebar by default --- packages/opencode/src/cli/cmd/tui/routes/session/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index 06be5dfbefbf..84239885cc21 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -153,7 +153,7 @@ export function Session() { }) const dimensions = useTerminalDimensions() - const [sidebar, setSidebar] = kv.signal<"auto" | "hide">("sidebar", "auto") + const [sidebar, setSidebar] = kv.signal<"auto" | "hide">("sidebar_visibility", "hide") const [sidebarOpen, setSidebarOpen] = createSignal(false) const [conceal, setConceal] = createSignal(true) const [showThinking, setShowThinking] = kv.signal("thinking_visibility", true)