From be9432a893dd1662c10ff41c7ab552bcba8f3e1b Mon Sep 17 00:00:00 2001
From: Dax <mail@thdxr.com>
Date: Wed, 15 Apr 2026 10:26:20 -0400
Subject: shared package (#22626)

---
 packages/ui/src/components/session-turn.tsx | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'packages/ui/src/components/session-turn.tsx')

diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx
index e891a6feb..6d43a575a 100644
--- a/packages/ui/src/components/session-turn.tsx
+++ b/packages/ui/src/components/session-turn.tsx
@@ -8,8 +8,8 @@ import type { SessionStatus } from "@opencode-ai/sdk/v2"
 import { useData } from "../context"
 import { useFileComponent } from "../context/file"
 
-import { Binary } from "@opencode-ai/util/binary"
-import { getDirectory, getFilename } from "@opencode-ai/util/path"
+import { Binary } from "@opencode-ai/shared/util/binary"
+import { getDirectory, getFilename } from "@opencode-ai/shared/util/path"
 import { createEffect, createMemo, createSignal, For, on, ParentProps, Show } from "solid-js"
 import { createStore } from "solid-js/store"
 import { Dynamic } from "solid-js/web"
-- 
cgit v1.2.3


From 3d6f90cb536ec30ff5091e1cbe3b1e619a93e1b0 Mon Sep 17 00:00:00 2001
From: Kit Langton <kit.langton@gmail.com>
Date: Wed, 15 Apr 2026 20:45:19 -0400
Subject: feat: add oxlint with correctness defaults (#22682)

---
 .oxlintrc.json                                     | 10 ++++++
 bun.lock                                           | 41 ++++++++++++++++++++++
 package.json                                       |  2 ++
 packages/app/src/components/file-tree.tsx          |  2 +-
 packages/app/src/components/terminal.tsx           |  2 +-
 .../app/src/context/global-sync/child-store.ts     |  4 +--
 packages/app/src/context/layout.tsx                |  4 +--
 .../console/app/src/routes/zen/util/handler.ts     |  2 +-
 packages/console/core/src/key.ts                   |  8 ++---
 packages/desktop-electron/src/main/apps.ts         |  2 +-
 packages/desktop-electron/src/main/shell-env.ts    |  2 +-
 packages/opencode/script/build.ts                  |  4 +--
 packages/opencode/src/agent/agent.ts               |  2 +-
 packages/opencode/src/cli/cmd/providers.ts         |  4 +--
 packages/opencode/src/config/tui.ts                |  2 +-
 packages/opencode/src/lsp/launch.ts                |  2 +-
 packages/opencode/src/plugin/cloudflare.ts         |  6 ++--
 packages/opencode/src/plugin/meta.ts               |  2 +-
 packages/opencode/src/provider/provider.ts         |  4 +--
 packages/opencode/src/server/instance/session.ts   |  2 +-
 packages/opencode/src/session/prompt.ts            |  2 +-
 packages/opencode/src/tool/bash.ts                 |  2 +-
 packages/opencode/test/cli/tui/theme-store.test.ts |  2 +-
 .../opencode/test/plugin/loader-shared.test.ts     | 10 +++---
 .../opencode/test/plugin/workspace-adaptor.test.ts |  2 +-
 packages/shared/src/util/path.ts                   |  8 ++---
 packages/ui/src/components/accordion.tsx           | 10 +++---
 packages/ui/src/components/app-icon.tsx            |  2 +-
 packages/ui/src/components/avatar.tsx              |  2 +-
 packages/ui/src/components/button.tsx              |  2 +-
 packages/ui/src/components/card.tsx                |  8 ++---
 packages/ui/src/components/collapsible.tsx         |  2 +-
 packages/ui/src/components/context-menu.tsx        | 32 ++++++++---------
 packages/ui/src/components/dialog.tsx              |  2 +-
 packages/ui/src/components/dock-surface.tsx        |  6 ++--
 packages/ui/src/components/dropdown-menu.tsx       | 32 ++++++++---------
 packages/ui/src/components/file-icon.tsx           |  2 +-
 packages/ui/src/components/file-ssr.tsx            |  4 +--
 packages/ui/src/components/file.tsx                |  2 +-
 packages/ui/src/components/hover-card.tsx          |  2 +-
 packages/ui/src/components/icon-button.tsx         |  2 +-
 packages/ui/src/components/icon.tsx                |  2 +-
 packages/ui/src/components/keybind.tsx             |  2 +-
 packages/ui/src/components/markdown.tsx            |  4 +--
 packages/ui/src/components/popover.tsx             |  2 +-
 packages/ui/src/components/progress-circle.tsx     |  2 +-
 packages/ui/src/components/progress.tsx            |  2 +-
 packages/ui/src/components/provider-icon.tsx       |  2 +-
 packages/ui/src/components/radio-group.tsx         |  2 +-
 packages/ui/src/components/resize-handle.tsx       |  2 +-
 packages/ui/src/components/select.tsx              |  6 ++--
 packages/ui/src/components/session-turn.tsx        |  2 +-
 packages/ui/src/components/spinner.tsx             |  2 +-
 .../ui/src/components/sticky-accordion-header.tsx  |  2 +-
 packages/ui/src/components/tabs.tsx                |  8 ++---
 packages/ui/src/components/tag.tsx                 |  2 +-
 packages/ui/src/components/toast.tsx               |  2 +-
 57 files changed, 165 insertions(+), 122 deletions(-)
 create mode 100644 .oxlintrc.json

(limited to 'packages/ui/src/components/session-turn.tsx')

diff --git a/.oxlintrc.json b/.oxlintrc.json
new file mode 100644
index 000000000..0875f3832
--- /dev/null
+++ b/.oxlintrc.json
@@ -0,0 +1,10 @@
+{
+  "$schema": "https://raw.githubusercontent.com/nicolo-ribaudo/oxc-project.github.io/refs/heads/json-schema/src/public/.oxlintrc.schema.json",
+  "rules": {
+    // Effect uses `function*` with Effect.gen/Effect.fnUntraced that don't always yield
+    "require-yield": "off",
+    // SolidJS uses `let ref: T | undefined` for JSX ref bindings assigned at runtime
+    "no-unassigned-vars": "off"
+  },
+  "ignorePatterns": ["**/node_modules", "**/dist", "**/.build", "**/.sst", "**/*.d.ts"]
+}
diff --git a/bun.lock b/bun.lock
index aeab042cf..48243e652 100644
--- a/bun.lock
+++ b/bun.lock
@@ -19,6 +19,7 @@
         "@typescript/native-preview": "catalog:",
         "glob": "13.0.5",
         "husky": "9.1.7",
+        "oxlint": "1.60.0",
         "prettier": "3.6.2",
         "semver": "^7.6.0",
         "sst": "3.18.10",
@@ -1693,6 +1694,44 @@
 
     "@oxc-transform/binding-win32-x64-msvc": ["@oxc-transform/binding-win32-x64-msvc@0.96.0", "", { "os": "win32", "cpu": "x64" }, "sha512-0fI0P0W7bSO/GCP/N5dkmtB9vBqCA4ggo1WmXTnxNJVmFFOtcA1vYm1I9jl8fxo+sucW2WnlpnI4fjKdo3JKxA=="],
 
+    "@oxlint/binding-android-arm-eabi": ["@oxlint/binding-android-arm-eabi@1.60.0", "", { "os": "android", "cpu": "arm" }, "sha512-YdeJKaZckDQL1qa62a1aKq/goyq48aX3yOxaaWqWb4sau4Ee4IiLbamftNLU3zbePky6QsDj6thnSSzHRBjDfA=="],
+
+    "@oxlint/binding-android-arm64": ["@oxlint/binding-android-arm64@1.60.0", "", { "os": "android", "cpu": "arm64" }, "sha512-7ANS7PpXCfq84xZQ8E5WPs14gwcuPcl+/8TFNXfpSu0CQBXz3cUo2fDpHT8v8HJN+Ut02eacvMAzTnc9s6X4tw=="],
+
+    "@oxlint/binding-darwin-arm64": ["@oxlint/binding-darwin-arm64@1.60.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-pJsgd9AfplLGBm1fIr25V6V14vMrayhx4uIQvlfH7jWs2SZwSrvi3TfgfJySB8T+hvyEH8K2zXljQiUnkgUnfQ=="],
+
+    "@oxlint/binding-darwin-x64": ["@oxlint/binding-darwin-x64@1.60.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ue1aXHX49ivwflKqGJc7zcd/LeLgbhaTcDCQStgx5x06AXgjEAZmvrlMuIkWd4AL4FHQe6QJ9f33z04Cg448VQ=="],
+
+    "@oxlint/binding-freebsd-x64": ["@oxlint/binding-freebsd-x64@1.60.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-YCyQzsQtusQw+gNRW9rRTifSO+Dt/+dtCl2NHoDMZqJlRTEZ/Oht9YnuporI9yiTx7+cB+eqzX3MtHHVHGIWhg=="],
+
+    "@oxlint/binding-linux-arm-gnueabihf": ["@oxlint/binding-linux-arm-gnueabihf@1.60.0", "", { "os": "linux", "cpu": "arm" }, "sha512-c7dxM2Zksa45Qw16i2iGY3Fti2NirJ38FrsBsKw+qcJ0OtqTsBgKJLF0xV+yLG56UH01Z8WRPgsw31e0MoRoGQ=="],
+
+    "@oxlint/binding-linux-arm-musleabihf": ["@oxlint/binding-linux-arm-musleabihf@1.60.0", "", { "os": "linux", "cpu": "arm" }, "sha512-ZWALoA42UYqBEP1Tbw9OWURgFGS1nWj2AAvLdY6ZcGx/Gj93qVCBKjcvwXMupZibYwFbi9s/rzqkZseb/6gVtQ=="],
+
+    "@oxlint/binding-linux-arm64-gnu": ["@oxlint/binding-linux-arm64-gnu@1.60.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-tpy+1w4p9hN5CicMCxqNy6ymfRtV5ayE573vFNjp1k1TN/qhLFgflveZoE/0++RlkHikBz2vY545NWm/hp7big=="],
+
+    "@oxlint/binding-linux-arm64-musl": ["@oxlint/binding-linux-arm64-musl@1.60.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-eDYDXZGhQAXyn6GwtwiX/qcLS0HlOLPJ/+iiIY8RYr+3P8oKBmgKxADLlniL6FtWfE7pPk7IGN9/xvDEvDvFeg=="],
+
+    "@oxlint/binding-linux-ppc64-gnu": ["@oxlint/binding-linux-ppc64-gnu@1.60.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-nxehly5XYBHUWI9VJX1bqCf9j/B43DaK/aS/T1fcxCpX3PA4Rm9BB54nPD1CKayT8xg6REN1ao+01hSRNgy8OA=="],
+
+    "@oxlint/binding-linux-riscv64-gnu": ["@oxlint/binding-linux-riscv64-gnu@1.60.0", "", { "os": "linux", "cpu": "none" }, "sha512-j1qf/NaUfOWQutjeoooNG1Q0zsK0XGmSu1uDLq3cctquRF3j7t9Hxqf/76ehCc5GEUAanth2W4Fa+XT1RFg/nw=="],
+
+    "@oxlint/binding-linux-riscv64-musl": ["@oxlint/binding-linux-riscv64-musl@1.60.0", "", { "os": "linux", "cpu": "none" }, "sha512-YELKPRefQ/q/h3RUmeRfPCUhh2wBvgV1RyZ/F9M9u8cDyXsQW2ojv1DeWQTt466yczDITjZnIOg/s05pk7Ve2A=="],
+
+    "@oxlint/binding-linux-s390x-gnu": ["@oxlint/binding-linux-s390x-gnu@1.60.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-JkO3C6Gki7Y6h/MiIkFKvHFOz98/YWvQ4WYbK9DLXACMP2rjULzkeGyAzorJE5S1dzLQGFgeqvN779kSFwoV1g=="],
+
+    "@oxlint/binding-linux-x64-gnu": ["@oxlint/binding-linux-x64-gnu@1.60.0", "", { "os": "linux", "cpu": "x64" }, "sha512-XjKHdFVCpZZZSWBCKyyqCq65s2AKXykMXkjLoKYODrD+f5toLhlwsMESscu8FbgnJQ4Y/dpR/zdazsahmgBJIA=="],
+
+    "@oxlint/binding-linux-x64-musl": ["@oxlint/binding-linux-x64-musl@1.60.0", "", { "os": "linux", "cpu": "x64" }, "sha512-js29ZWIuPhNWzY8NC7KoffEMEeWG105vbmm+8EOJsC+T/jHBiKIJEUF78+F/IrgEWMMP9N0kRND4Pp75+xAhKg=="],
+
+    "@oxlint/binding-openharmony-arm64": ["@oxlint/binding-openharmony-arm64@1.60.0", "", { "os": "none", "cpu": "arm64" }, "sha512-H+PUITKHk04stFpWj3x3Kg08Afp/bcXSBi0EhasR5a0Vw7StXHTzdl655PUI0fB4qdh2Wsu6Dsi+3ACxPoyQnA=="],
+
+    "@oxlint/binding-win32-arm64-msvc": ["@oxlint/binding-win32-arm64-msvc@1.60.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-WA/yc7f7ZfCefBXVzNHn1Ztulb1EFwNBb4jMZ6pjML0zz6pHujlF3Q3jySluz3XHl/GNeMTntG1seUBWVMlMag=="],
+
+    "@oxlint/binding-win32-ia32-msvc": ["@oxlint/binding-win32-ia32-msvc@1.60.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-33YxL1sqwYNZXtn3MD/4dno6s0xeedXOJlT1WohkVD565WvohClZUr7vwKdAk954n4xiEWJkewiCr+zLeq7AeA=="],
+
+    "@oxlint/binding-win32-x64-msvc": ["@oxlint/binding-win32-x64-msvc@1.60.0", "", { "os": "win32", "cpu": "x64" }, "sha512-JOro4ZcfBLamJCyfURQmOQByoorgOdx3ZjAkSqnb/CyG/i+lN3KoV5LAgk5ZAW6DPq7/Cx7n23f8DuTWXTWgyQ=="],
+
     "@pagefind/darwin-arm64": ["@pagefind/darwin-arm64@1.5.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MXpI+7HsAdPkvJ0gk9xj9g541BCqBZOBbdwj9g6lB5LCj6kSV6nqDSjzcAJwvOsfu0fjwvC8hQU+ecfhp+MpiQ=="],
 
     "@pagefind/darwin-x64": ["@pagefind/darwin-x64@1.5.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-IojxFWMEJe0RQ7PQ3KXQsPIImNsbpPYpoZ+QUDrL8fAl/O27IX+LVLs74/UzEZy5uA2LD8Nz1AiwKr72vrkZQw=="],
@@ -4073,6 +4112,8 @@
 
     "oxc-transform": ["oxc-transform@0.96.0", "", { "optionalDependencies": { "@oxc-transform/binding-android-arm64": "0.96.0", "@oxc-transform/binding-darwin-arm64": "0.96.0", "@oxc-transform/binding-darwin-x64": "0.96.0", "@oxc-transform/binding-freebsd-x64": "0.96.0", "@oxc-transform/binding-linux-arm-gnueabihf": "0.96.0", "@oxc-transform/binding-linux-arm-musleabihf": "0.96.0", "@oxc-transform/binding-linux-arm64-gnu": "0.96.0", "@oxc-transform/binding-linux-arm64-musl": "0.96.0", "@oxc-transform/binding-linux-riscv64-gnu": "0.96.0", "@oxc-transform/binding-linux-s390x-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-musl": "0.96.0", "@oxc-transform/binding-wasm32-wasi": "0.96.0", "@oxc-transform/binding-win32-arm64-msvc": "0.96.0", "@oxc-transform/binding-win32-x64-msvc": "0.96.0" } }, "sha512-dQPNIF+gHpSkmC0+Vg9IktNyhcn28Y8R3eTLyzn52UNymkasLicl3sFAtz7oEVuFmCpgGjaUTKkwk+jW2cHpDQ=="],
 
+    "oxlint": ["oxlint@1.60.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.60.0", "@oxlint/binding-android-arm64": "1.60.0", "@oxlint/binding-darwin-arm64": "1.60.0", "@oxlint/binding-darwin-x64": "1.60.0", "@oxlint/binding-freebsd-x64": "1.60.0", "@oxlint/binding-linux-arm-gnueabihf": "1.60.0", "@oxlint/binding-linux-arm-musleabihf": "1.60.0", "@oxlint/binding-linux-arm64-gnu": "1.60.0", "@oxlint/binding-linux-arm64-musl": "1.60.0", "@oxlint/binding-linux-ppc64-gnu": "1.60.0", "@oxlint/binding-linux-riscv64-gnu": "1.60.0", "@oxlint/binding-linux-riscv64-musl": "1.60.0", "@oxlint/binding-linux-s390x-gnu": "1.60.0", "@oxlint/binding-linux-x64-gnu": "1.60.0", "@oxlint/binding-linux-x64-musl": "1.60.0", "@oxlint/binding-openharmony-arm64": "1.60.0", "@oxlint/binding-win32-arm64-msvc": "1.60.0", "@oxlint/binding-win32-ia32-msvc": "1.60.0", "@oxlint/binding-win32-x64-msvc": "1.60.0" }, "peerDependencies": { "oxlint-tsgolint": ">=0.18.0" }, "optionalPeers": ["oxlint-tsgolint"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-tnRzTWiWJ9pg3ftRWnD0+Oqh78L6ZSwcEudvCZaER0PIqiAnNyXj5N1dPwjmNpDalkKS9m/WMLN1CTPUBPmsgw=="],
+
     "p-cancelable": ["p-cancelable@2.1.1", "", {}, "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="],
 
     "p-defer": ["p-defer@3.0.0", "", {}, "sha512-ugZxsxmtTln604yeYd29EGrNhazN2lywetzpKhfmQjW/VJmhpDmWbiX+h0zL8V91R0UXkhb3KtPmyq9PZw3aYw=="],
diff --git a/package.json b/package.json
index abe1b5d36..8c5ae9195 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
     "dev:web": "bun --cwd packages/app dev",
     "dev:console": "ulimit -n 10240 2>/dev/null; bun run --cwd packages/console/app dev",
     "dev:storybook": "bun --cwd packages/storybook storybook",
+    "lint": "oxlint",
     "typecheck": "bun turbo typecheck",
     "postinstall": "bun run --cwd packages/opencode fix-node-pty",
     "prepare": "husky",
@@ -85,6 +86,7 @@
     "@typescript/native-preview": "catalog:",
     "glob": "13.0.5",
     "husky": "9.1.7",
+    "oxlint": "1.60.0",
     "prettier": "3.6.2",
     "semver": "^7.6.0",
     "sst": "3.18.10",
diff --git a/packages/app/src/components/file-tree.tsx b/packages/app/src/components/file-tree.tsx
index 930832fb6..8fbecf671 100644
--- a/packages/app/src/components/file-tree.tsx
+++ b/packages/app/src/components/file-tree.tsx
@@ -149,7 +149,7 @@ const FileTreeNode = (
       classList={{
         "w-full min-w-0 h-6 flex items-center justify-start gap-x-1.5 rounded-md px-1.5 py-0 text-left hover:bg-surface-raised-base-hover active:bg-surface-base-active transition-colors cursor-pointer": true,
         "bg-surface-base-active": local.node.path === local.active,
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
         [local.nodeClass ?? ""]: !!local.nodeClass,
       }}
diff --git a/packages/app/src/components/terminal.tsx b/packages/app/src/components/terminal.tsx
index 96a865b9e..9b7ef83b2 100644
--- a/packages/app/src/components/terminal.tsx
+++ b/packages/app/src/components/terminal.tsx
@@ -634,7 +634,7 @@ export const Terminal = (props: TerminalProps) => {
       tabIndex={-1}
       style={{ "background-color": terminalColors().background }}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         "select-text": true,
         "size-full px-6 py-3 font-mono relative overflow-hidden": true,
         [local.class ?? ""]: !!local.class,
diff --git a/packages/app/src/context/global-sync/child-store.ts b/packages/app/src/context/global-sync/child-store.ts
index 5678491f8..3fe67e4fb 100644
--- a/packages/app/src/context/global-sync/child-store.ts
+++ b/packages/app/src/context/global-sync/child-store.ts
@@ -243,8 +243,8 @@ export function createChildStoreManager(input: {
     const cached = metaCache.get(directory)
     if (!cached) return
     const previous = store.projectMeta ?? {}
-    const icon = patch.icon ? { ...(previous.icon ?? {}), ...patch.icon } : previous.icon
-    const commands = patch.commands ? { ...(previous.commands ?? {}), ...patch.commands } : previous.commands
+    const icon = patch.icon ? { ...previous.icon, ...patch.icon } : previous.icon
+    const commands = patch.commands ? { ...previous.commands, ...patch.commands } : previous.commands
     const next = {
       ...previous,
       ...patch,
diff --git a/packages/app/src/context/layout.tsx b/packages/app/src/context/layout.tsx
index bab3d39f3..87f11d2b6 100644
--- a/packages/app/src/context/layout.tsx
+++ b/packages/app/src/context/layout.tsx
@@ -344,7 +344,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
           return
         }
 
-        setStore("sessionView", sessionKey, "scroll", (prev) => ({ ...(prev ?? {}), ...next }))
+        setStore("sessionView", sessionKey, "scroll", (prev) => ({ ...prev, ...next }))
         prune(keep)
       },
     })
@@ -399,7 +399,7 @@ export const { use: useLayout, provider: LayoutProvider } = createSimpleContext(
         local?.icon?.color !== undefined
 
       const base = {
-        ...(metadata ?? {}),
+        ...metadata,
         ...project,
         icon: {
           url: metadata?.icon?.url,
diff --git a/packages/console/app/src/routes/zen/util/handler.ts b/packages/console/app/src/routes/zen/util/handler.ts
index 58df61809..358d8736c 100644
--- a/packages/console/app/src/routes/zen/util/handler.ts
+++ b/packages/console/app/src/routes/zen/util/handler.ts
@@ -144,7 +144,7 @@ export async function handler(
         providerInfo.modifyBody({
           ...createBodyConverter(opts.format, providerInfo.format)(body),
           model: providerInfo.model,
-          ...(providerInfo.payloadModifier ?? {}),
+          ...providerInfo.payloadModifier,
           ...Object.fromEntries(
             Object.entries(providerInfo.payloadMappings ?? {})
               .map(([k, v]) => [k, input.request.headers.get(v)])
diff --git a/packages/console/core/src/key.ts b/packages/console/core/src/key.ts
index 688f19b3d..d1aae1524 100644
--- a/packages/console/core/src/key.ts
+++ b/packages/console/core/src/key.ts
@@ -24,11 +24,9 @@ export namespace Key {
         .innerJoin(AuthTable, and(eq(UserTable.accountID, AuthTable.accountID), eq(AuthTable.provider, "email")))
         .where(
           and(
-            ...[
-              eq(KeyTable.workspaceID, Actor.workspace()),
+            eq(KeyTable.workspaceID, Actor.workspace()),
               isNull(KeyTable.timeDeleted),
               ...(Actor.userRole() === "admin" ? [] : [eq(KeyTable.userID, Actor.userID())]),
-            ],
           ),
         )
         .orderBy(sql`${KeyTable.name} DESC`),
@@ -84,11 +82,9 @@ export namespace Key {
         })
         .where(
           and(
-            ...[
-              eq(KeyTable.id, input.id),
+            eq(KeyTable.id, input.id),
               eq(KeyTable.workspaceID, Actor.workspace()),
               ...(Actor.userRole() === "admin" ? [] : [eq(KeyTable.userID, Actor.userID())]),
-            ],
           ),
         ),
     )
diff --git a/packages/desktop-electron/src/main/apps.ts b/packages/desktop-electron/src/main/apps.ts
index 2b4603789..d21b6cc9e 100644
--- a/packages/desktop-electron/src/main/apps.ts
+++ b/packages/desktop-electron/src/main/apps.ts
@@ -20,7 +20,7 @@ export function wslPath(path: string, mode: "windows" | "linux" | null): string
   try {
     if (path.startsWith("~")) {
       const suffix = path.slice(1)
-      const cmd = `wslpath ${flag} \"$HOME${suffix.replace(/\"/g, '\\"')}\"`
+      const cmd = `wslpath ${flag} "$HOME${suffix.replace(/"/g, '\\"')}"`
       const output = execFileSync("wsl", ["-e", "sh", "-lc", cmd])
       return output.toString().trim()
     }
diff --git a/packages/desktop-electron/src/main/shell-env.ts b/packages/desktop-electron/src/main/shell-env.ts
index 8453a5730..f57677323 100644
--- a/packages/desktop-electron/src/main/shell-env.ts
+++ b/packages/desktop-electron/src/main/shell-env.ts
@@ -82,7 +82,7 @@ export function loadShellEnv(shell: string) {
 
 export function mergeShellEnv(shell: Record<string, string> | null, env: Record<string, string>) {
   return {
-    ...(shell || {}),
+    ...shell,
     ...env,
   }
 }
diff --git a/packages/opencode/script/build.ts b/packages/opencode/script/build.ts
index 6d1087f28..d2628974f 100755
--- a/packages/opencode/script/build.ts
+++ b/packages/opencode/script/build.ts
@@ -211,9 +211,7 @@ for (const item of targets) {
       execArgv: [`--user-agent=opencode/${Script.version}`, "--use-system-ca", "--"],
       windows: {},
     },
-    files: {
-      ...(embeddedFileMap ? { "opencode-web-ui.gen.ts": embeddedFileMap } : {}),
-    },
+    files: (embeddedFileMap ? { "opencode-web-ui.gen.ts": embeddedFileMap } : {}),
     entrypoints: [
       "./src/index.ts",
       parserWorker,
diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts
index 8857696b0..ba38c8efe 100644
--- a/packages/opencode/src/agent/agent.ts
+++ b/packages/opencode/src/agent/agent.ts
@@ -368,7 +368,7 @@ export namespace Agent {
                   )),
               {
                 role: "user",
-                content: `Create an agent configuration based on this request: \"${input.description}\".\n\nIMPORTANT: The following identifiers already exist and must NOT be used: ${existing.map((i) => i.name).join(", ")}\n  Return ONLY the JSON object, no other text, do not wrap in backticks`,
+                content: `Create an agent configuration based on this request: "${input.description}".\n\nIMPORTANT: The following identifiers already exist and must NOT be used: ${existing.map((i) => i.name).join(", ")}\n  Return ONLY the JSON object, no other text, do not wrap in backticks`,
               },
             ],
             model: language,
diff --git a/packages/opencode/src/cli/cmd/providers.ts b/packages/opencode/src/cli/cmd/providers.ts
index d2afbabfb..06f9fdf1d 100644
--- a/packages/opencode/src/cli/cmd/providers.ts
+++ b/packages/opencode/src/cli/cmd/providers.ts
@@ -40,12 +40,10 @@ async function handlePluginAuth(plugin: { auth: PluginAuth }, provider: string,
   } else if (plugin.auth.methods.length > 1) {
     const method = await prompts.select({
       message: "Login method",
-      options: [
-        ...plugin.auth.methods.map((x, index) => ({
+      options: plugin.auth.methods.map((x, index) => ({
           label: x.label,
           value: index.toString(),
         })),
-      ],
     })
     if (prompts.isCancel(method)) throw new UI.CancelledError()
     index = parseInt(method)
diff --git a/packages/opencode/src/config/tui.ts b/packages/opencode/src/config/tui.ts
index 12bd7e0da..e64b226c1 100644
--- a/packages/opencode/src/config/tui.ts
+++ b/packages/opencode/src/config/tui.ts
@@ -125,7 +125,7 @@ export namespace TuiConfig {
       }
     }
 
-    const keybinds = { ...(acc.result.keybinds ?? {}) }
+    const keybinds = { ...acc.result.keybinds }
     if (process.platform === "win32") {
       // Native Windows terminals do not support POSIX suspend, so prefer prompt undo.
       keybinds.terminal_suspend = "none"
diff --git a/packages/opencode/src/lsp/launch.ts b/packages/opencode/src/lsp/launch.ts
index b7dca446f..51a7c209b 100644
--- a/packages/opencode/src/lsp/launch.ts
+++ b/packages/opencode/src/lsp/launch.ts
@@ -9,7 +9,7 @@ export function spawn(cmd: string, argsOrOpts?: string[] | Process.Options, opts
   const args = Array.isArray(argsOrOpts) ? [...argsOrOpts] : []
   const cfg = Array.isArray(argsOrOpts) ? opts : argsOrOpts
   const proc = Process.spawn([cmd, ...args], {
-    ...(cfg ?? {}),
+    ...cfg,
     stdin: "pipe",
     stdout: "pipe",
     stderr: "pipe",
diff --git a/packages/opencode/src/plugin/cloudflare.ts b/packages/opencode/src/plugin/cloudflare.ts
index e20a488a3..267d1ed2f 100644
--- a/packages/opencode/src/plugin/cloudflare.ts
+++ b/packages/opencode/src/plugin/cloudflare.ts
@@ -1,8 +1,7 @@
 import type { Hooks, PluginInput } from "@opencode-ai/plugin"
 
 export async function CloudflareWorkersAuthPlugin(_input: PluginInput): Promise<Hooks> {
-  const prompts = [
-    ...(!process.env.CLOUDFLARE_ACCOUNT_ID
+  const prompts = (!process.env.CLOUDFLARE_ACCOUNT_ID
       ? [
           {
             type: "text" as const,
@@ -11,8 +10,7 @@ export async function CloudflareWorkersAuthPlugin(_input: PluginInput): Promise<
             placeholder: "e.g. 1234567890abcdef1234567890abcdef",
           },
         ]
-      : []),
-  ]
+      : [])
 
   return {
     auth: {
diff --git a/packages/opencode/src/plugin/meta.ts b/packages/opencode/src/plugin/meta.ts
index f40895469..3f02f543e 100644
--- a/packages/opencode/src/plugin/meta.ts
+++ b/packages/opencode/src/plugin/meta.ts
@@ -174,7 +174,7 @@ export namespace PluginMeta {
       const entry = store[id]
       if (!entry) return
       entry.themes = {
-        ...(entry.themes ?? {}),
+        ...entry.themes,
         [name]: theme,
       }
       await Filesystem.writeJson(file, store)
diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts
index 9ec5dfc6b..c029e5c5c 100644
--- a/packages/opencode/src/provider/provider.ts
+++ b/packages/opencode/src/provider/provider.ts
@@ -551,13 +551,13 @@ export namespace Provider {
         const aiGatewayHeaders = {
           "User-Agent": `opencode/${Installation.VERSION} gitlab-ai-provider/${GITLAB_PROVIDER_VERSION} (${os.platform()} ${os.release()}; ${os.arch()})`,
           "anthropic-beta": "context-1m-2025-08-07",
-          ...(providerConfig?.options?.aiGatewayHeaders || {}),
+          ...providerConfig?.options?.aiGatewayHeaders,
         }
 
         const featureFlags = {
           duo_agent_platform_agentic_chat: true,
           duo_agent_platform: true,
-          ...(providerConfig?.options?.featureFlags || {}),
+          ...providerConfig?.options?.featureFlags,
         }
 
         return {
diff --git a/packages/opencode/src/server/instance/session.ts b/packages/opencode/src/server/instance/session.ts
index 0bce3085e..c606af854 100644
--- a/packages/opencode/src/server/instance/session.ts
+++ b/packages/opencode/src/server/instance/session.ts
@@ -695,7 +695,7 @@ export const SessionRoutes = lazy(() =>
           url.searchParams.set("limit", query.limit.toString())
           url.searchParams.set("before", page.cursor)
           c.header("Access-Control-Expose-Headers", "Link, X-Next-Cursor")
-          c.header("Link", `<${url.toString()}>; rel=\"next\"`)
+          c.header("Link", `<${url.toString()}>; rel="next"`)
           c.header("X-Next-Cursor", page.cursor)
         }
         return c.json(page.items)
diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts
index ffd074d3f..f2a160e26 100644
--- a/packages/opencode/src/session/prompt.ts
+++ b/packages/opencode/src/session/prompt.ts
@@ -497,7 +497,7 @@ NOTE: At any point in time through this workflow you should feel free to ask the
 
                 const truncated = yield* truncate.output(textParts.join("\n\n"), {}, input.agent)
                 const metadata = {
-                  ...(result.metadata ?? {}),
+                  ...result.metadata,
                   truncated: truncated.truncated,
                   ...(truncated.truncated && { outputPath: truncated.outputPath }),
                 }
diff --git a/packages/opencode/src/tool/bash.ts b/packages/opencode/src/tool/bash.ts
index 3bb936944..7a124dada 100644
--- a/packages/opencode/src/tool/bash.ts
+++ b/packages/opencode/src/tool/bash.ts
@@ -176,7 +176,7 @@ function dynamic(text: string, ps: boolean) {
 }
 
 function prefix(text: string) {
-  const match = /[?*\[]/.exec(text)
+  const match = /[?*[]/.exec(text)
   if (!match) return text
   if (match.index === 0) return
   return text.slice(0, match.index)
diff --git a/packages/opencode/test/cli/tui/theme-store.test.ts b/packages/opencode/test/cli/tui/theme-store.test.ts
index 936e3e6f7..9ebfc4320 100644
--- a/packages/opencode/test/cli/tui/theme-store.test.ts
+++ b/packages/opencode/test/cli/tui/theme-store.test.ts
@@ -41,7 +41,7 @@ test("hasTheme checks theme presence", () => {
 test("resolveTheme rejects circular color refs", () => {
   const item = structuredClone(DEFAULT_THEMES.opencode)
   item.defs = {
-    ...(item.defs ?? {}),
+    ...item.defs,
     one: "two",
     two: "one",
   }
diff --git a/packages/opencode/test/plugin/loader-shared.test.ts b/packages/opencode/test/plugin/loader-shared.test.ts
index 5f1e2b168..4265e83c5 100644
--- a/packages/opencode/test/plugin/loader-shared.test.ts
+++ b/packages/opencode/test/plugin/loader-shared.test.ts
@@ -48,7 +48,7 @@ describe("plugin.loader.shared", () => {
           file,
           [
             "export default async () => {",
-            `  await Bun.write(${JSON.stringify(mark)}, \"called\")`,
+            `  await Bun.write(${JSON.stringify(mark)}, "called")`,
             "  return {}",
             "}",
             "",
@@ -78,8 +78,8 @@ describe("plugin.loader.shared", () => {
           file,
           [
             "const run = async () => {",
-            `  const text = await Bun.file(${JSON.stringify(mark)}).text().catch(() => \"\")`,
-            `  await Bun.write(${JSON.stringify(mark)}, text + \"1\")`,
+            `  const text = await Bun.file(${JSON.stringify(mark)}).text().catch(() => "")`,
+            `  await Bun.write(${JSON.stringify(mark)}, text + "1")`,
             "  return {}",
             "}",
             "export default run",
@@ -715,7 +715,7 @@ describe("plugin.loader.shared", () => {
             "const plugin = {",
             '  id: "demo.object",',
             "  server: async () => {",
-            `    await Bun.write(${JSON.stringify(mark)}, \"called\")`,
+            `    await Bun.write(${JSON.stringify(mark)}, "called")`,
             "    return {}",
             "  },",
             "}",
@@ -833,7 +833,7 @@ export default {
             "export default {",
             '  id: "demo.pure",',
             "  server: async () => {",
-            `    await Bun.write(${JSON.stringify(mark)}, \"called\")`,
+            `    await Bun.write(${JSON.stringify(mark)}, "called")`,
             "    return {}",
             "  },",
             "}",
diff --git a/packages/opencode/test/plugin/workspace-adaptor.test.ts b/packages/opencode/test/plugin/workspace-adaptor.test.ts
index a5f56df5e..669a822a2 100644
--- a/packages/opencode/test/plugin/workspace-adaptor.test.ts
+++ b/packages/opencode/test/plugin/workspace-adaptor.test.ts
@@ -39,7 +39,7 @@ describe("plugin.workspace", () => {
             '    name: "plug",',
             '    description: "plugin workspace adaptor",',
             "    configure(input) {",
-            `      return { ...input, name: \"plug\", branch: \"plug/main\", directory: ${JSON.stringify(space)} }`,
+            `      return { ...input, name: "plug", branch: "plug/main", directory: ${JSON.stringify(space)} }`,
             "    },",
             "    async create(input) {",
             `      await Bun.write(${JSON.stringify(mark)}, JSON.stringify(input))`,
diff --git a/packages/shared/src/util/path.ts b/packages/shared/src/util/path.ts
index bb191f512..b87316358 100644
--- a/packages/shared/src/util/path.ts
+++ b/packages/shared/src/util/path.ts
@@ -1,14 +1,14 @@
 export function getFilename(path: string | undefined) {
   if (!path) return ""
-  const trimmed = path.replace(/[\/\\]+$/, "")
-  const parts = trimmed.split(/[\/\\]/)
+  const trimmed = path.replace(/[/\\]+$/, "")
+  const parts = trimmed.split(/[/\\]/)
   return parts[parts.length - 1] ?? ""
 }
 
 export function getDirectory(path: string | undefined) {
   if (!path) return ""
-  const trimmed = path.replace(/[\/\\]+$/, "")
-  const parts = trimmed.split(/[\/\\]/)
+  const trimmed = path.replace(/[/\\]+$/, "")
+  const parts = trimmed.split(/[/\\]/)
   return parts.slice(0, parts.length - 1).join("/") + "/"
 }
 
diff --git a/packages/ui/src/components/accordion.tsx b/packages/ui/src/components/accordion.tsx
index 535d38e3d..3179b8a15 100644
--- a/packages/ui/src/components/accordion.tsx
+++ b/packages/ui/src/components/accordion.tsx
@@ -15,7 +15,7 @@ function AccordionRoot(props: AccordionProps) {
       {...rest}
       data-component="accordion"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     />
@@ -29,7 +29,7 @@ function AccordionItem(props: AccordionItemProps) {
       {...rest}
       data-slot="accordion-item"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     />
@@ -43,7 +43,7 @@ function AccordionHeader(props: ParentProps<AccordionHeaderProps>) {
       {...rest}
       data-slot="accordion-header"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -59,7 +59,7 @@ function AccordionTrigger(props: ParentProps<AccordionTriggerProps>) {
       {...rest}
       data-slot="accordion-trigger"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -75,7 +75,7 @@ function AccordionContent(props: ParentProps<AccordionContentProps>) {
       {...rest}
       data-slot="accordion-content"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
diff --git a/packages/ui/src/components/app-icon.tsx b/packages/ui/src/components/app-icon.tsx
index f8b587ff2..541dfc570 100644
--- a/packages/ui/src/components/app-icon.tsx
+++ b/packages/ui/src/components/app-icon.tsx
@@ -77,7 +77,7 @@ export const AppIcon: Component<AppIconProps> = (props) => {
       alt={local.alt ?? ""}
       draggable={local.draggable ?? false}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     />
diff --git a/packages/ui/src/components/avatar.tsx b/packages/ui/src/components/avatar.tsx
index c1617b265..035c2d304 100644
--- a/packages/ui/src/components/avatar.tsx
+++ b/packages/ui/src/components/avatar.tsx
@@ -38,7 +38,7 @@ export function Avatar(props: AvatarProps) {
       data-size={split.size || "normal"}
       data-has-image={src ? "" : undefined}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
       style={{
diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx
index 7f974b2f7..d1652145f 100644
--- a/packages/ui/src/components/button.tsx
+++ b/packages/ui/src/components/button.tsx
@@ -20,7 +20,7 @@ export function Button(props: ButtonProps) {
       data-variant={split.variant || "secondary"}
       data-icon={split.icon}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
diff --git a/packages/ui/src/components/card.tsx b/packages/ui/src/components/card.tsx
index 7a1bd5e45..320aba718 100644
--- a/packages/ui/src/components/card.tsx
+++ b/packages/ui/src/components/card.tsx
@@ -53,7 +53,7 @@ export function Card(props: CardProps) {
       data-variant={variant()}
       style={mix(split.style, accent())}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -76,7 +76,7 @@ export function CardTitle(props: CardTitleProps) {
       {...rest}
       data-slot="card-title"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -97,7 +97,7 @@ export function CardDescription(props: ComponentProps<"div">) {
       {...rest}
       data-slot="card-description"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -113,7 +113,7 @@ export function CardActions(props: ComponentProps<"div">) {
       {...rest}
       data-slot="card-actions"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
diff --git a/packages/ui/src/components/collapsible.tsx b/packages/ui/src/components/collapsible.tsx
index 8b5cd825c..b2a603264 100644
--- a/packages/ui/src/components/collapsible.tsx
+++ b/packages/ui/src/components/collapsible.tsx
@@ -15,7 +15,7 @@ function CollapsibleRoot(props: CollapsibleProps) {
       data-component="collapsible"
       data-variant={local.variant || "normal"}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
       {...others}
diff --git a/packages/ui/src/components/context-menu.tsx b/packages/ui/src/components/context-menu.tsx
index afdaff7b8..f4566a17a 100644
--- a/packages/ui/src/components/context-menu.tsx
+++ b/packages/ui/src/components/context-menu.tsx
@@ -33,7 +33,7 @@ function ContextMenuTrigger(props: ParentProps<ContextMenuTriggerProps>) {
       {...rest}
       data-slot="context-menu-trigger"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -49,7 +49,7 @@ function ContextMenuIcon(props: ParentProps<ContextMenuIconProps>) {
       {...rest}
       data-slot="context-menu-icon"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -69,7 +69,7 @@ function ContextMenuContent(props: ParentProps<ContextMenuContentProps>) {
       {...rest}
       data-component="context-menu-content"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -85,7 +85,7 @@ function ContextMenuArrow(props: ContextMenuArrowProps) {
       {...rest}
       data-slot="context-menu-arrow"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     />
@@ -99,7 +99,7 @@ function ContextMenuSeparator(props: ContextMenuSeparatorProps) {
       {...rest}
       data-slot="context-menu-separator"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     />
@@ -113,7 +113,7 @@ function ContextMenuGroup(props: ParentProps<ContextMenuGroupProps>) {
       {...rest}
       data-slot="context-menu-group"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -129,7 +129,7 @@ function ContextMenuGroupLabel(props: ParentProps<ContextMenuGroupLabelProps>) {
       {...rest}
       data-slot="context-menu-group-label"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -145,7 +145,7 @@ function ContextMenuItem(props: ParentProps<ContextMenuItemProps>) {
       {...rest}
       data-slot="context-menu-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -161,7 +161,7 @@ function ContextMenuItemLabel(props: ParentProps<ContextMenuItemLabelProps>) {
       {...rest}
       data-slot="context-menu-item-label"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -177,7 +177,7 @@ function ContextMenuItemDescription(props: ParentProps<ContextMenuItemDescriptio
       {...rest}
       data-slot="context-menu-item-description"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -193,7 +193,7 @@ function ContextMenuItemIndicator(props: ParentProps<ContextMenuItemIndicatorPro
       {...rest}
       data-slot="context-menu-item-indicator"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -209,7 +209,7 @@ function ContextMenuRadioGroup(props: ParentProps<ContextMenuRadioGroupProps>) {
       {...rest}
       data-slot="context-menu-radio-group"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -225,7 +225,7 @@ function ContextMenuRadioItem(props: ParentProps<ContextMenuRadioItemProps>) {
       {...rest}
       data-slot="context-menu-radio-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -241,7 +241,7 @@ function ContextMenuCheckboxItem(props: ParentProps<ContextMenuCheckboxItemProps
       {...rest}
       data-slot="context-menu-checkbox-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -261,7 +261,7 @@ function ContextMenuSubTrigger(props: ParentProps<ContextMenuSubTriggerProps>) {
       {...rest}
       data-slot="context-menu-sub-trigger"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -277,7 +277,7 @@ function ContextMenuSubContent(props: ParentProps<ContextMenuSubContentProps>) {
       {...rest}
       data-component="context-menu-sub-content"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
diff --git a/packages/ui/src/components/dialog.tsx b/packages/ui/src/components/dialog.tsx
index ce7704f37..981e3f45d 100644
--- a/packages/ui/src/components/dialog.tsx
+++ b/packages/ui/src/components/dialog.tsx
@@ -28,7 +28,7 @@ export function Dialog(props: DialogProps) {
           data-slot="dialog-content"
           data-no-header={!props.title && !props.action ? "" : undefined}
           classList={{
-            ...(props.classList ?? {}),
+            ...props.classList,
             [props.class ?? ""]: !!props.class,
           }}
           onOpenAutoFocus={(e) => {
diff --git a/packages/ui/src/components/dock-surface.tsx b/packages/ui/src/components/dock-surface.tsx
index 1c4af2ed5..06cf2a5eb 100644
--- a/packages/ui/src/components/dock-surface.tsx
+++ b/packages/ui/src/components/dock-surface.tsx
@@ -11,7 +11,7 @@ export function DockShell(props: ComponentProps<"div">) {
       {...rest}
       data-dock-surface="shell"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -27,7 +27,7 @@ export function DockShellForm(props: ComponentProps<"form">) {
       {...rest}
       data-dock-surface="shell"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
@@ -44,7 +44,7 @@ export function DockTray(props: DockTrayProps) {
       data-dock-surface="tray"
       data-dock-attach={split.attach || "none"}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
diff --git a/packages/ui/src/components/dropdown-menu.tsx b/packages/ui/src/components/dropdown-menu.tsx
index efb2b45ca..259cb791a 100644
--- a/packages/ui/src/components/dropdown-menu.tsx
+++ b/packages/ui/src/components/dropdown-menu.tsx
@@ -33,7 +33,7 @@ function DropdownMenuTrigger(props: ParentProps<DropdownMenuTriggerProps>) {
       {...rest}
       data-slot="dropdown-menu-trigger"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -49,7 +49,7 @@ function DropdownMenuIcon(props: ParentProps<DropdownMenuIconProps>) {
       {...rest}
       data-slot="dropdown-menu-icon"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -69,7 +69,7 @@ function DropdownMenuContent(props: ParentProps<DropdownMenuContentProps>) {
       {...rest}
       data-component="dropdown-menu-content"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -85,7 +85,7 @@ function DropdownMenuArrow(props: DropdownMenuArrowProps) {
       {...rest}
       data-slot="dropdown-menu-arrow"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     />
@@ -99,7 +99,7 @@ function DropdownMenuSeparator(props: DropdownMenuSeparatorProps) {
       {...rest}
       data-slot="dropdown-menu-separator"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     />
@@ -113,7 +113,7 @@ function DropdownMenuGroup(props: ParentProps<DropdownMenuGroupProps>) {
       {...rest}
       data-slot="dropdown-menu-group"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -129,7 +129,7 @@ function DropdownMenuGroupLabel(props: ParentProps<DropdownMenuGroupLabelProps>)
       {...rest}
       data-slot="dropdown-menu-group-label"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -145,7 +145,7 @@ function DropdownMenuItem(props: ParentProps<DropdownMenuItemProps>) {
       {...rest}
       data-slot="dropdown-menu-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -161,7 +161,7 @@ function DropdownMenuItemLabel(props: ParentProps<DropdownMenuItemLabelProps>) {
       {...rest}
       data-slot="dropdown-menu-item-label"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -177,7 +177,7 @@ function DropdownMenuItemDescription(props: ParentProps<DropdownMenuItemDescript
       {...rest}
       data-slot="dropdown-menu-item-description"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -193,7 +193,7 @@ function DropdownMenuItemIndicator(props: ParentProps<DropdownMenuItemIndicatorP
       {...rest}
       data-slot="dropdown-menu-item-indicator"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -209,7 +209,7 @@ function DropdownMenuRadioGroup(props: ParentProps<DropdownMenuRadioGroupProps>)
       {...rest}
       data-slot="dropdown-menu-radio-group"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -225,7 +225,7 @@ function DropdownMenuRadioItem(props: ParentProps<DropdownMenuRadioItemProps>) {
       {...rest}
       data-slot="dropdown-menu-radio-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -241,7 +241,7 @@ function DropdownMenuCheckboxItem(props: ParentProps<DropdownMenuCheckboxItemPro
       {...rest}
       data-slot="dropdown-menu-checkbox-item"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -261,7 +261,7 @@ function DropdownMenuSubTrigger(props: ParentProps<DropdownMenuSubTriggerProps>)
       {...rest}
       data-slot="dropdown-menu-sub-trigger"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
@@ -277,7 +277,7 @@ function DropdownMenuSubContent(props: ParentProps<DropdownMenuSubContentProps>)
       {...rest}
       data-component="dropdown-menu-sub-content"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
diff --git a/packages/ui/src/components/file-icon.tsx b/packages/ui/src/components/file-icon.tsx
index 133cb169c..d66ee1c25 100644
--- a/packages/ui/src/components/file-icon.tsx
+++ b/packages/ui/src/components/file-icon.tsx
@@ -18,7 +18,7 @@ export const FileIcon: Component<FileIconProps> = (props) => {
       data-component="file-icon"
       {...rest}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
diff --git a/packages/ui/src/components/file-ssr.tsx b/packages/ui/src/components/file-ssr.tsx
index fed5c8931..ad05555bd 100644
--- a/packages/ui/src/components/file-ssr.tsx
+++ b/packages/ui/src/components/file-ssr.tsx
@@ -99,7 +99,7 @@ function DiffSSRViewer<T>(props: SSRDiffFileProps<T>) {
           {
             ...createDefaultOptions(props.diffStyle),
             ...others,
-            ...(local.preloadedDiff.options ?? {}),
+            ...local.preloadedDiff.options,
           },
           virtualizer,
           virtualMetrics,
@@ -109,7 +109,7 @@ function DiffSSRViewer<T>(props: SSRDiffFileProps<T>) {
           {
             ...createDefaultOptions(props.diffStyle),
             ...others,
-            ...(local.preloadedDiff.options ?? {}),
+            ...local.preloadedDiff.options,
           },
           workerPool,
         )
diff --git a/packages/ui/src/components/file.tsx b/packages/ui/src/components/file.tsx
index 51c289273..fd902b2e0 100644
--- a/packages/ui/src/components/file.tsx
+++ b/packages/ui/src/components/file.tsx
@@ -655,7 +655,7 @@ function ViewerShell(props: {
       style={styleVariables}
       class="relative outline-none"
       classList={{
-        ...(props.classList || {}),
+        ...props.classList,
         [props.class ?? ""]: !!props.class,
       }}
       ref={(el) => (props.viewer.wrapper = el)}
diff --git a/packages/ui/src/components/hover-card.tsx b/packages/ui/src/components/hover-card.tsx
index 8330375aa..4e6647313 100644
--- a/packages/ui/src/components/hover-card.tsx
+++ b/packages/ui/src/components/hover-card.tsx
@@ -20,7 +20,7 @@ export function HoverCard(props: HoverCardProps) {
         <Kobalte.Content
           data-component="hover-card-content"
           classList={{
-            ...(local.classList ?? {}),
+            ...local.classList,
             [local.class ?? ""]: !!local.class,
           }}
         >
diff --git a/packages/ui/src/components/icon-button.tsx b/packages/ui/src/components/icon-button.tsx
index 89ab00fcd..457283aa0 100644
--- a/packages/ui/src/components/icon-button.tsx
+++ b/packages/ui/src/components/icon-button.tsx
@@ -19,7 +19,7 @@ export function IconButton(props: ComponentProps<"button"> & IconButtonProps) {
       data-size={split.size || "normal"}
       data-variant={split.variant || "secondary"}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx
index e2eaf107a..08726d0ff 100644
--- a/packages/ui/src/components/icon.tsx
+++ b/packages/ui/src/components/icon.tsx
@@ -117,7 +117,7 @@ export function Icon(props: IconProps) {
       <svg
         data-slot="icon-svg"
         classList={{
-          ...(local.classList || {}),
+          ...local.classList,
           [local.class ?? ""]: !!local.class,
         }}
         fill="none"
diff --git a/packages/ui/src/components/keybind.tsx b/packages/ui/src/components/keybind.tsx
index a0fa0483f..5c347cb54 100644
--- a/packages/ui/src/components/keybind.tsx
+++ b/packages/ui/src/components/keybind.tsx
@@ -10,7 +10,7 @@ export function Keybind(props: KeybindProps) {
     <span
       data-component="keybind"
       classList={{
-        ...(props.classList ?? {}),
+        ...props.classList,
         [props.class ?? ""]: !!props.class,
       }}
     >
diff --git a/packages/ui/src/components/markdown.tsx b/packages/ui/src/components/markdown.tsx
index f3037da8b..28653512e 100644
--- a/packages/ui/src/components/markdown.tsx
+++ b/packages/ui/src/components/markdown.tsx
@@ -50,7 +50,7 @@ function escape(text: string) {
     .replace(/&/g, "&amp;")
     .replace(/</g, "&lt;")
     .replace(/>/g, "&gt;")
-    .replace(/\"/g, "&quot;")
+    .replace(/"/g, "&quot;")
     .replace(/'/g, "&#39;")
 }
 
@@ -338,7 +338,7 @@ export function Markdown(
     <div
       data-component="markdown"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
       ref={setRoot}
diff --git a/packages/ui/src/components/popover.tsx b/packages/ui/src/components/popover.tsx
index 8263640a5..be5b78519 100644
--- a/packages/ui/src/components/popover.tsx
+++ b/packages/ui/src/components/popover.tsx
@@ -106,7 +106,7 @@ export function Popover<T extends ValidComponent = "div">(props: PopoverProps<T>
       ref={(el: HTMLElement | undefined) => setState("contentRef", el)}
       data-component="popover-content"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
       style={local.style}
diff --git a/packages/ui/src/components/progress-circle.tsx b/packages/ui/src/components/progress-circle.tsx
index 02bd36bb7..992fb62e8 100644
--- a/packages/ui/src/components/progress-circle.tsx
+++ b/packages/ui/src/components/progress-circle.tsx
@@ -32,7 +32,7 @@ export function ProgressCircle(props: ProgressCircleProps) {
       fill="none"
       data-component="progress-circle"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
diff --git a/packages/ui/src/components/progress.tsx b/packages/ui/src/components/progress.tsx
index bfe10a1d1..7cbe5d6bc 100644
--- a/packages/ui/src/components/progress.tsx
+++ b/packages/ui/src/components/progress.tsx
@@ -15,7 +15,7 @@ export function Progress(props: ProgressProps) {
       {...others}
       data-component="progress"
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
diff --git a/packages/ui/src/components/provider-icon.tsx b/packages/ui/src/components/provider-icon.tsx
index edfdd0357..7c0eb3d04 100644
--- a/packages/ui/src/components/provider-icon.tsx
+++ b/packages/ui/src/components/provider-icon.tsx
@@ -15,7 +15,7 @@ export const ProviderIcon: Component<ProviderIconProps> = (props) => {
       data-component="provider-icon"
       {...rest}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
     >
diff --git a/packages/ui/src/components/radio-group.tsx b/packages/ui/src/components/radio-group.tsx
index 544e852e4..9151a24b0 100644
--- a/packages/ui/src/components/radio-group.tsx
+++ b/packages/ui/src/components/radio-group.tsx
@@ -56,7 +56,7 @@ export function RadioGroup<T>(props: RadioGroupProps<T>) {
       data-fill={local.fill ? "" : undefined}
       data-pad={local.pad ?? "normal"}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
       value={local.current ? getValue(local.current) : undefined}
diff --git a/packages/ui/src/components/resize-handle.tsx b/packages/ui/src/components/resize-handle.tsx
index e2eed1bb7..d7774a684 100644
--- a/packages/ui/src/components/resize-handle.tsx
+++ b/packages/ui/src/components/resize-handle.tsx
@@ -73,7 +73,7 @@ export function ResizeHandle(props: ResizeHandleProps) {
       data-direction={local.direction}
       data-edge={local.edge ?? (local.direction === "vertical" ? "start" : "end")}
       classList={{
-        ...(local.classList ?? {}),
+        ...local.classList,
         [local.class ?? ""]: !!local.class,
       }}
       onMouseDown={handleMouseDown}
diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx
index 61804a951..67becf2d9 100644
--- a/packages/ui/src/components/select.tsx
+++ b/packages/ui/src/components/select.tsx
@@ -104,7 +104,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">)
           {...itemProps}
           data-slot="select-select-item"
           classList={{
-            ...(local.classList ?? {}),
+            ...local.classList,
             [local.class ?? ""]: !!local.class,
           }}
           onPointerEnter={() => move(itemProps.item.rawValue)}
@@ -141,7 +141,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">)
         variant={props.variant}
         style={local.triggerStyle}
         classList={{
-          ...(local.classList ?? {}),
+          ...local.classList,
           [local.class ?? ""]: !!local.class,
         }}
       >
@@ -160,7 +160,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">)
       <Kobalte.Portal>
         <Kobalte.Content
           classList={{
-            ...(local.classList ?? {}),
+            ...local.classList,
             [local.class ?? ""]: !!local.class,
           }}
           data-component="select-content"
diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx
index 6d43a575a..2e5f9e38b 100644
--- a/packages/ui/src/components/session-turn.tsx
+++ b/packages/ui/src/components/session-turn.tsx
@@ -110,7 +110,7 @@ function partState(part: PartType, showReasoningSummaries: boolean) {
 function clean(value: string) {
   return value
     .replace(/`([^`]+)`/g, "$1")
-    .replace(/\[([^\]]+)\]\([^\)]+\)/g, "$1")
+    .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1")
     .replace(/[*_~]+/g, "")
     .trim()
 }
diff --git a/packages/ui/src/components/spinner.tsx b/packages/ui/src/components/spinner.tsx
index 3d029d976..f8aacb6e2 100644
--- a/packages/ui/src/components/spinner.tsx
+++ b/packages/ui/src/components/spinner.tsx
@@ -23,7 +23,7 @@ export function Spinner(props: {
       viewBox="0 0 15 15"
       data-component="spinner"
       classList={{
-        ...(props.classList ?? {}),
+        ...props.classList,
         [props.class ?? ""]: !!props.class,
       }}
       fill="currentColor"
diff --git a/packages/ui/src/components/sticky-accordion-header.tsx b/packages/ui/src/components/sticky-accordion-header.tsx
index 89d733449..b877aa16e 100644
--- a/packages/ui/src/components/sticky-accordion-header.tsx
+++ b/packages/ui/src/components/sticky-accordion-header.tsx
@@ -8,7 +8,7 @@ export function StickyAccordionHeader(
     <Accordion.Header
       data-component="sticky-accordion-header"
       classList={{
-        ...(props.classList ?? {}),
+        ...props.classList,
         [props.class ?? ""]: !!props.class,
       }}
     >
diff --git a/packages/ui/src/components/tabs.tsx b/packages/ui/src/components/tabs.tsx
index 396504dd7..f46e9bfb3 100644
--- a/packages/ui/src/components/tabs.tsx
+++ b/packages/ui/src/components/tabs.tsx
@@ -27,7 +27,7 @@ function TabsRoot(props: TabsProps) {
       data-variant={split.variant || "normal"}
       data-orientation={split.orientation || "horizontal"}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     />
@@ -41,7 +41,7 @@ function TabsList(props: TabsListProps) {
       {...rest}
       data-slot="tabs-list"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     />
@@ -63,7 +63,7 @@ function TabsTrigger(props: ParentProps<TabsTriggerProps>) {
       data-slot="tabs-trigger-wrapper"
       data-value={props.value}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
       onMouseDown={(e) => {
@@ -104,7 +104,7 @@ function TabsContent(props: ParentProps<TabsContentProps>) {
       {...rest}
       data-slot="tabs-content"
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
diff --git a/packages/ui/src/components/tag.tsx b/packages/ui/src/components/tag.tsx
index 428eedd0f..c54e4d474 100644
--- a/packages/ui/src/components/tag.tsx
+++ b/packages/ui/src/components/tag.tsx
@@ -12,7 +12,7 @@ export function Tag(props: TagProps) {
       data-component="tag"
       data-size={split.size || "normal"}
       classList={{
-        ...(split.classList ?? {}),
+        ...split.classList,
         [split.class ?? ""]: !!split.class,
       }}
     >
diff --git a/packages/ui/src/components/toast.tsx b/packages/ui/src/components/toast.tsx
index e8062a2a8..599cf2a9e 100644
--- a/packages/ui/src/components/toast.tsx
+++ b/packages/ui/src/components/toast.tsx
@@ -30,7 +30,7 @@ function ToastRoot(props: ToastRootComponentProps) {
     <Kobalte
       data-component="toast"
       classList={{
-        ...(props.classList ?? {}),
+        ...props.classList,
         [props.class ?? ""]: !!props.class,
       }}
       {...props}
-- 
cgit v1.2.3


From 8aa0f9fe9515ba0234ab6a0a58c868068913bb05 Mon Sep 17 00:00:00 2001
From: Kit Langton <kit.langton@gmail.com>
Date: Wed, 15 Apr 2026 23:50:47 -0400
Subject: feat: enable type-aware no-base-to-string rule, fix 56 violations
 (#22750)

---
 .oxlintrc.json                                     |  4 ++++
 .../workspace/[id]/billing/black-section.tsx       |  4 ++--
 .../[id]/billing/monthly-limit-section.tsx         |  4 ++--
 .../workspace/[id]/billing/reload-section.tsx      | 22 +++++++++++-----------
 .../src/routes/workspace/[id]/go/lite-section.tsx  |  4 ++--
 .../src/routes/workspace/[id]/keys/key-section.tsx |  8 ++++----
 .../workspace/[id]/members/member-section.tsx      | 22 +++++++++++-----------
 .../src/routes/workspace/[id]/model-section.tsx    |  8 ++++----
 .../src/routes/workspace/[id]/provider-section.tsx | 17 ++++++++++-------
 .../workspace/[id]/settings/settings-section.tsx   |  4 ++--
 packages/opencode/script/schema.ts                 |  2 +-
 packages/opencode/src/effect/logger.ts             |  2 ++
 .../opencode/src/plugin/github-copilot/copilot.ts  |  2 +-
 packages/opencode/src/provider/transform.ts        |  4 ++--
 packages/opencode/src/pty/service.ts               |  2 +-
 packages/opencode/src/snapshot/snapshot.ts         |  2 +-
 packages/opencode/src/tool/apply_patch.ts          | 10 +++++++++-
 packages/opencode/src/util/error.ts                |  1 +
 packages/opencode/src/v2/session-entry.ts          |  1 +
 packages/opencode/test/config/config.test.ts       |  4 ++--
 packages/shared/src/util/retry.ts                  |  1 +
 packages/shared/test/util/effect-flock.test.ts     |  1 +
 .../.storybook/mocks/app/context/language.ts       |  1 +
 packages/ui/src/components/file.tsx                |  3 +++
 packages/ui/src/components/session-turn.tsx        |  1 +
 packages/web/src/components/share/part.tsx         |  8 +++++++-
 26 files changed, 87 insertions(+), 55 deletions(-)

(limited to 'packages/ui/src/components/session-turn.tsx')

diff --git a/.oxlintrc.json b/.oxlintrc.json
index e16c8408d..a0b620649 100644
--- a/.oxlintrc.json
+++ b/.oxlintrc.json
@@ -1,9 +1,13 @@
 {
   "$schema": "https://raw.githubusercontent.com/nicolo-ribaudo/oxc-project.github.io/refs/heads/json-schema/src/public/.oxlintrc.schema.json",
+  "options": {
+    "typeAware": true
+  },
   "categories": {
     "suspicious": "warn"
   },
   "rules": {
+    "typescript/no-base-to-string": "warn",
     // Effect uses `function*` with Effect.gen/Effect.fnUntraced that don't always yield
     "require-yield": "off",
     // SolidJS uses `let ref: T | undefined` for JSX ref bindings assigned at runtime
diff --git a/packages/console/app/src/routes/workspace/[id]/billing/black-section.tsx b/packages/console/app/src/routes/workspace/[id]/billing/black-section.tsx
index b8f089864..5b4389466 100644
--- a/packages/console/app/src/routes/workspace/[id]/billing/black-section.tsx
+++ b/packages/console/app/src/routes/workspace/[id]/billing/black-section.tsx
@@ -116,9 +116,9 @@ const createSessionUrl = action(async (workspaceID: string, returnUrl: string) =
 
 const setUseBalance = action(async (form: FormData) => {
   "use server"
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
-  const useBalance = form.get("useBalance")?.toString() === "true"
+  const useBalance = (form.get("useBalance") as string | null) === "true"
 
   return json(
     await withActor(async () => {
diff --git a/packages/console/app/src/routes/workspace/[id]/billing/monthly-limit-section.tsx b/packages/console/app/src/routes/workspace/[id]/billing/monthly-limit-section.tsx
index ef54b8409..7da1de238 100644
--- a/packages/console/app/src/routes/workspace/[id]/billing/monthly-limit-section.tsx
+++ b/packages/console/app/src/routes/workspace/[id]/billing/monthly-limit-section.tsx
@@ -10,11 +10,11 @@ import { formError, localizeError } from "~/lib/form-error"
 
 const setMonthlyLimit = action(async (form: FormData) => {
   "use server"
-  const limit = form.get("limit")?.toString()
+  const limit = form.get("limit") as string | null
   if (!limit) return { error: formError.limitRequired }
   const numericLimit = parseInt(limit)
   if (numericLimit < 0) return { error: formError.monthlyLimitInvalid }
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
   return json(
     await withActor(
diff --git a/packages/console/app/src/routes/workspace/[id]/billing/reload-section.tsx b/packages/console/app/src/routes/workspace/[id]/billing/reload-section.tsx
index a25963ab0..c9a72c087 100644
--- a/packages/console/app/src/routes/workspace/[id]/billing/reload-section.tsx
+++ b/packages/console/app/src/routes/workspace/[id]/billing/reload-section.tsx
@@ -12,7 +12,7 @@ import { formError, formErrorReloadAmountMin, formErrorReloadTriggerMin, localiz
 
 const reload = action(async (form: FormData) => {
   "use server"
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
   return json(await withActor(() => Billing.reload(), workspaceID), {
     revalidate: queryBillingInfo.key,
@@ -21,11 +21,11 @@ const reload = action(async (form: FormData) => {
 
 const setReload = action(async (form: FormData) => {
   "use server"
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
-  const reloadValue = form.get("reload")?.toString() === "true"
-  const amountStr = form.get("reloadAmount")?.toString()
-  const triggerStr = form.get("reloadTrigger")?.toString()
+  const reloadValue = (form.get("reload") as string | null) === "true"
+  const amountStr = form.get("reloadAmount") as string | null
+  const triggerStr = form.get("reloadTrigger") as string | null
 
   const reloadAmount = amountStr && amountStr.trim() !== "" ? parseInt(amountStr) : null
   const reloadTrigger = triggerStr && triggerStr.trim() !== "" ? parseInt(triggerStr) : null
@@ -91,8 +91,8 @@ export function ReloadSection() {
     const info = billingInfo()!
     setStore("show", true)
     setStore("reload", true)
-    setStore("reloadAmount", info.reloadAmount.toString())
-    setStore("reloadTrigger", info.reloadTrigger.toString())
+    setStore("reloadAmount", String(info.reloadAmount))
+    setStore("reloadTrigger", String(info.reloadTrigger))
   }
 
   function hide() {
@@ -152,11 +152,11 @@ export function ReloadSection() {
                 data-component="input"
                 name="reloadAmount"
                 type="number"
-                min={billingInfo()?.reloadAmountMin.toString()}
+                min={String(billingInfo()?.reloadAmountMin ?? "")}
                 step="1"
                 value={store.reloadAmount}
                 onInput={(e) => setStore("reloadAmount", e.currentTarget.value)}
-                placeholder={billingInfo()?.reloadAmount.toString()}
+                placeholder={String(billingInfo()?.reloadAmount ?? "")}
                 disabled={!store.reload}
               />
             </div>
@@ -166,11 +166,11 @@ export function ReloadSection() {
                 data-component="input"
                 name="reloadTrigger"
                 type="number"
-                min={billingInfo()?.reloadTriggerMin.toString()}
+                min={String(billingInfo()?.reloadTriggerMin ?? "")}
                 step="1"
                 value={store.reloadTrigger}
                 onInput={(e) => setStore("reloadTrigger", e.currentTarget.value)}
-                placeholder={billingInfo()?.reloadTrigger.toString()}
+                placeholder={String(billingInfo()?.reloadTrigger ?? "")}
                 disabled={!store.reload}
               />
             </div>
diff --git a/packages/console/app/src/routes/workspace/[id]/go/lite-section.tsx b/packages/console/app/src/routes/workspace/[id]/go/lite-section.tsx
index 95ff7af2b..d0f812182 100644
--- a/packages/console/app/src/routes/workspace/[id]/go/lite-section.tsx
+++ b/packages/console/app/src/routes/workspace/[id]/go/lite-section.tsx
@@ -120,9 +120,9 @@ const createSessionUrl = action(async (workspaceID: string, returnUrl: string) =
 
 const setLiteUseBalance = action(async (form: FormData) => {
   "use server"
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
-  const useBalance = form.get("useBalance")?.toString() === "true"
+  const useBalance = (form.get("useBalance") as string | null) === "true"
 
   return json(
     await withActor(async () => {
diff --git a/packages/console/app/src/routes/workspace/[id]/keys/key-section.tsx b/packages/console/app/src/routes/workspace/[id]/keys/key-section.tsx
index 837ab743a..cb273a422 100644
--- a/packages/console/app/src/routes/workspace/[id]/keys/key-section.tsx
+++ b/packages/console/app/src/routes/workspace/[id]/keys/key-section.tsx
@@ -12,18 +12,18 @@ import { formError, localizeError } from "~/lib/form-error"
 
 const removeKey = action(async (form: FormData) => {
   "use server"
-  const id = form.get("id")?.toString()
+  const id = form.get("id") as string | null
   if (!id) return { error: formError.idRequired }
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
   return json(await withActor(() => Key.remove({ id }), workspaceID), { revalidate: listKeys.key })
 }, "key.remove")
 
 const createKey = action(async (form: FormData) => {
   "use server"
-  const name = form.get("name")?.toString().trim()
+  const name = (form.get("name") as string | null)?.trim()
   if (!name) return { error: formError.nameRequired }
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
   return json(
     await withActor(
diff --git a/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx b/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx
index 5a440632f..00edb400c 100644
--- a/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx
+++ b/packages/console/app/src/routes/workspace/[id]/members/member-section.tsx
@@ -24,13 +24,13 @@ const listMembers = query(async (workspaceID: string) => {
 
 const inviteMember = action(async (form: FormData) => {
   "use server"
-  const email = form.get("email")?.toString().trim()
+  const email = (form.get("email") as string | null)?.trim()
   if (!email) return { error: formError.emailRequired }
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
-  const role = form.get("role")?.toString() as (typeof UserRole)[number]
+  const role = form.get("role") as (typeof UserRole)[number] | null
   if (!role) return { error: formError.roleRequired }
-  const limit = form.get("limit")?.toString()
+  const limit = form.get("limit") as string | null
   const monthlyLimit = limit && limit.trim() !== "" ? parseInt(limit) : null
   if (monthlyLimit !== null && monthlyLimit < 0) return { error: formError.monthlyLimitInvalid }
   return json(
@@ -47,9 +47,9 @@ const inviteMember = action(async (form: FormData) => {
 
 const removeMember = action(async (form: FormData) => {
   "use server"
-  const id = form.get("id")?.toString()
+  const id = form.get("id") as string | null
   if (!id) return { error: formError.idRequired }
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
   return json(
     await withActor(
@@ -66,13 +66,13 @@ const removeMember = action(async (form: FormData) => {
 const updateMember = action(async (form: FormData) => {
   "use server"
 
-  const id = form.get("id")?.toString()
+  const id = form.get("id") as string | null
   if (!id) return { error: formError.idRequired }
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
-  const role = form.get("role")?.toString() as (typeof UserRole)[number]
+  const role = form.get("role") as (typeof UserRole)[number] | null
   if (!role) return { error: formError.roleRequired }
-  const limit = form.get("limit")?.toString()
+  const limit = form.get("limit") as string | null
   const monthlyLimit = limit && limit.trim() !== "" ? parseInt(limit) : null
   if (monthlyLimit !== null && monthlyLimit < 0) return { error: formError.monthlyLimitInvalid }
 
@@ -118,7 +118,7 @@ function MemberRow(props: {
     }
     setStore("editing", true)
     setStore("selectedRole", props.member.role)
-    setStore("limit", props.member.monthlyLimit?.toString() ?? "")
+    setStore("limit", props.member.monthlyLimit != null ? String(props.member.monthlyLimit) : "")
   }
 
   function hide() {
diff --git a/packages/console/app/src/routes/workspace/[id]/model-section.tsx b/packages/console/app/src/routes/workspace/[id]/model-section.tsx
index bf19f81cd..b9cdf3bc3 100644
--- a/packages/console/app/src/routes/workspace/[id]/model-section.tsx
+++ b/packages/console/app/src/routes/workspace/[id]/model-section.tsx
@@ -67,11 +67,11 @@ const getModelsInfo = query(async (workspaceID: string) => {
 
 const updateModel = action(async (form: FormData) => {
   "use server"
-  const model = form.get("model")?.toString()
+  const model = form.get("model") as string | null
   if (!model) return { error: formError.modelRequired }
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
-  const enabled = form.get("enabled")?.toString() === "true"
+  const enabled = (form.get("enabled") as string | null) === "true"
   return json(
     withActor(async () => {
       if (enabled) {
@@ -163,7 +163,7 @@ export function ModelSection() {
                           <form action={updateModel} method="post">
                             <input type="hidden" name="model" value={id} />
                             <input type="hidden" name="workspaceID" value={params.id} />
-                            <input type="hidden" name="enabled" value={isEnabled().toString()} />
+                            <input type="hidden" name="enabled" value={String(isEnabled())} />
                             <label data-slot="model-toggle-label">
                               <input
                                 type="checkbox"
diff --git a/packages/console/app/src/routes/workspace/[id]/provider-section.tsx b/packages/console/app/src/routes/workspace/[id]/provider-section.tsx
index fe04bf7c0..acdd89742 100644
--- a/packages/console/app/src/routes/workspace/[id]/provider-section.tsx
+++ b/packages/console/app/src/routes/workspace/[id]/provider-section.tsx
@@ -21,9 +21,9 @@ function maskCredentials(credentials: string) {
 
 const removeProvider = action(async (form: FormData) => {
   "use server"
-  const provider = form.get("provider")?.toString()
+  const provider = form.get("provider") as string | null
   if (!provider) return { error: formError.providerRequired }
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
   return json(await withActor(() => Provider.remove({ provider }), workspaceID), {
     revalidate: listProviders.key,
@@ -32,11 +32,11 @@ const removeProvider = action(async (form: FormData) => {
 
 const saveProvider = action(async (form: FormData) => {
   "use server"
-  const provider = form.get("provider")?.toString()
-  const credentials = form.get("credentials")?.toString()
+  const provider = form.get("provider") as string | null
+  const credentials = form.get("credentials") as string | null
   if (!provider) return { error: formError.providerRequired }
   if (!credentials) return { error: formError.apiKeyRequired }
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
   return json(
     await withActor(
@@ -59,10 +59,13 @@ function ProviderRow(props: { provider: Provider }) {
   const params = useParams()
   const i18n = useI18n()
   const providers = createAsync(() => listProviders(params.id!))
-  const saveSubmission = useSubmission(saveProvider, ([fd]) => fd.get("provider")?.toString() === props.provider.key)
+  const saveSubmission = useSubmission(
+    saveProvider,
+    ([fd]) => (fd.get("provider") as string | null) === props.provider.key,
+  )
   const removeSubmission = useSubmission(
     removeProvider,
-    ([fd]) => fd.get("provider")?.toString() === props.provider.key,
+    ([fd]) => (fd.get("provider") as string | null) === props.provider.key,
   )
   const [store, setStore] = createStore({ editing: false })
 
diff --git a/packages/console/app/src/routes/workspace/[id]/settings/settings-section.tsx b/packages/console/app/src/routes/workspace/[id]/settings/settings-section.tsx
index 5e8331e26..a9950c41e 100644
--- a/packages/console/app/src/routes/workspace/[id]/settings/settings-section.tsx
+++ b/packages/console/app/src/routes/workspace/[id]/settings/settings-section.tsx
@@ -30,10 +30,10 @@ const getWorkspaceInfo = query(async (workspaceID: string) => {
 
 const updateWorkspace = action(async (form: FormData) => {
   "use server"
-  const name = form.get("name")?.toString().trim()
+  const name = (form.get("name") as string | null)?.trim()
   if (!name) return { error: formError.workspaceNameRequired }
   if (name.length > 255) return { error: formError.nameTooLong }
-  const workspaceID = form.get("workspaceID")?.toString()
+  const workspaceID = form.get("workspaceID") as string | null
   if (!workspaceID) return { error: formError.workspaceRequired }
   return json(
     await withActor(
diff --git a/packages/opencode/script/schema.ts b/packages/opencode/script/schema.ts
index 4aa27423b..cf63d6743 100755
--- a/packages/opencode/script/schema.ts
+++ b/packages/opencode/script/schema.ts
@@ -33,7 +33,7 @@ function generate(schema: z.ZodType) {
           schema.examples = [schema.default]
         }
 
-        schema.description = [schema.description || "", `default: \`${schema.default}\``]
+        schema.description = [schema.description || "", `default: \`${String(schema.default)}\``]
           .filter(Boolean)
           .join("\n\n")
           .trim()
diff --git a/packages/opencode/src/effect/logger.ts b/packages/opencode/src/effect/logger.ts
index 97b614fc0..21e0fc43a 100644
--- a/packages/opencode/src/effect/logger.ts
+++ b/packages/opencode/src/effect/logger.ts
@@ -15,7 +15,9 @@ const clean = (input?: Fields): Fields =>
   Object.fromEntries(Object.entries(input ?? {}).filter((entry) => entry[1] !== undefined && entry[1] !== null))
 
 const text = (input: unknown): string => {
+  // oxlint-disable-next-line no-base-to-string
   if (Array.isArray(input)) return input.map((item) => String(item)).join(" ")
+  // oxlint-disable-next-line no-base-to-string
   return input === undefined ? "" : String(input)
 }
 
diff --git a/packages/opencode/src/plugin/github-copilot/copilot.ts b/packages/opencode/src/plugin/github-copilot/copilot.ts
index eeea21924..c1318287c 100644
--- a/packages/opencode/src/plugin/github-copilot/copilot.ts
+++ b/packages/opencode/src/plugin/github-copilot/copilot.ts
@@ -93,7 +93,7 @@ export async function CopilotAuthPlugin(input: PluginInput): Promise<Hooks> {
             const info = await getAuth()
             if (info.type !== "oauth") return fetch(request, init)
 
-            const url = request instanceof URL ? request.href : request.toString()
+            const url = request instanceof URL ? request.href : typeof request === "string" ? request : request.url
             const { isVision, isAgent } = iife(() => {
               try {
                 const body = typeof init?.body === "string" ? JSON.parse(init.body) : init?.body
diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts
index a0d3e2258..5fa39441c 100644
--- a/packages/opencode/src/provider/transform.ts
+++ b/packages/opencode/src/provider/transform.ts
@@ -274,7 +274,7 @@ export namespace ProviderTransform {
 
         // Check for empty base64 image data
         if (part.type === "image") {
-          const imageStr = part.image.toString()
+          const imageStr = String(part.image)
           if (imageStr.startsWith("data:")) {
             const match = imageStr.match(/^data:([^;]+);base64,(.*)$/)
             if (match && (!match[2] || match[2].length === 0)) {
@@ -286,7 +286,7 @@ export namespace ProviderTransform {
           }
         }
 
-        const mime = part.type === "image" ? part.image.toString().split(";")[0].replace("data:", "") : part.mediaType
+        const mime = part.type === "image" ? String(part.image).split(";")[0].replace("data:", "") : part.mediaType
         const filename = part.type === "file" ? part.filename : undefined
         const modality = mimeToModality(mime)
         if (!modality) return part
diff --git a/packages/opencode/src/pty/service.ts b/packages/opencode/src/pty/service.ts
index a4ebd0696..0c810be88 100644
--- a/packages/opencode/src/pty/service.ts
+++ b/packages/opencode/src/pty/service.ts
@@ -346,7 +346,7 @@ export const layer = Layer.effect(
 
       return {
         onMessage: (message: string | ArrayBuffer) => {
-          session.process.write(String(message))
+          session.process.write(typeof message === "string" ? message : new TextDecoder().decode(message))
         },
         onClose: () => {
           log.info("client disconnected from session", { id })
diff --git a/packages/opencode/src/snapshot/snapshot.ts b/packages/opencode/src/snapshot/snapshot.ts
index 8d8118131..7a5c0a4dc 100644
--- a/packages/opencode/src/snapshot/snapshot.ts
+++ b/packages/opencode/src/snapshot/snapshot.ts
@@ -116,7 +116,7 @@ export const layer: Layer.Layer<
             Effect.succeed({
               code: ChildProcessSpawner.ExitCode(1),
               text: "",
-              stderr: String(err),
+              stderr: err instanceof Error ? err.message : String(err),
             }),
           ),
         )
diff --git a/packages/opencode/src/tool/apply_patch.ts b/packages/opencode/src/tool/apply_patch.ts
index b9877d8fe..2d8a50101 100644
--- a/packages/opencode/src/tool/apply_patch.ts
+++ b/packages/opencode/src/tool/apply_patch.ts
@@ -145,7 +145,15 @@ export const ApplyPatchTool = Tool.define(
           case "delete": {
             const contentToDelete = yield* afs
               .readFileString(filePath)
-              .pipe(Effect.catch((error) => Effect.fail(new Error(`apply_patch verification failed: ${error}`))))
+              .pipe(
+                Effect.catch((error) =>
+                  Effect.fail(
+                    new Error(
+                      `apply_patch verification failed: ${error instanceof Error ? error.message : String(error)}`,
+                    ),
+                  ),
+                ),
+              )
             const deleteDiff = trimDiff(createTwoFilesPatch(filePath, filePath, contentToDelete, ""))
 
             const deletions = contentToDelete.split("\n").length
diff --git a/packages/opencode/src/util/error.ts b/packages/opencode/src/util/error.ts
index ea1c79178..75fef9fc9 100644
--- a/packages/opencode/src/util/error.ts
+++ b/packages/opencode/src/util/error.ts
@@ -60,6 +60,7 @@ export function errorData(error: unknown) {
       acc[key] = value
       return acc
     }
+    // oxlint-disable-next-line no-base-to-string -- intentional coercion of arbitrary error properties
     acc[key] = value instanceof Error ? value.message : String(value)
     return acc
   }, {})
diff --git a/packages/opencode/src/v2/session-entry.ts b/packages/opencode/src/v2/session-entry.ts
index a60d8c6c7..490f18422 100644
--- a/packages/opencode/src/v2/session-entry.ts
+++ b/packages/opencode/src/v2/session-entry.ts
@@ -202,6 +202,7 @@ export namespace SessionEntry {
         case "tool.input.delta": {
           if (!pendingAssistant) break
           const match = pendingAssistant.content.findLast((x) => x.type === "tool")
+          // oxlint-disable-next-line no-base-to-string -- event.delta is a Schema.String (runtime string)
           if (match) match.state.input += event.delta
           break
         }
diff --git a/packages/opencode/test/config/config.test.ts b/packages/opencode/test/config/config.test.ts
index bc9fe5b01..6a79cf644 100644
--- a/packages/opencode/test/config/config.test.ts
+++ b/packages/opencode/test/config/config.test.ts
@@ -1801,7 +1801,7 @@ test("project config overrides remote well-known config", async () => {
   const originalFetch = globalThis.fetch
   let fetchedUrl: string | undefined
   globalThis.fetch = mock((url: string | URL | Request) => {
-    const urlStr = url.toString()
+    const urlStr = url instanceof Request ? url.url : url instanceof URL ? url.href : url
     if (urlStr.includes(".well-known/opencode")) {
       fetchedUrl = urlStr
       return Promise.resolve(
@@ -1858,7 +1858,7 @@ test("wellknown URL with trailing slash is normalized", async () => {
   const originalFetch = globalThis.fetch
   let fetchedUrl: string | undefined
   globalThis.fetch = mock((url: string | URL | Request) => {
-    const urlStr = url.toString()
+    const urlStr = url instanceof Request ? url.url : url instanceof URL ? url.href : url
     if (urlStr.includes(".well-known/opencode")) {
       fetchedUrl = urlStr
       return Promise.resolve(
diff --git a/packages/shared/src/util/retry.ts b/packages/shared/src/util/retry.ts
index 0014a604c..831d23800 100644
--- a/packages/shared/src/util/retry.ts
+++ b/packages/shared/src/util/retry.ts
@@ -19,6 +19,7 @@ const TRANSIENT_MESSAGES = [
 
 function isTransientError(error: unknown): boolean {
   if (!error) return false
+  // oxlint-disable-next-line no-base-to-string -- error is unknown, intentional coercion for message matching
   const message = String(error instanceof Error ? error.message : error).toLowerCase()
   return TRANSIENT_MESSAGES.some((m) => message.includes(m))
 }
diff --git a/packages/shared/test/util/effect-flock.test.ts b/packages/shared/test/util/effect-flock.test.ts
index 6e094c2e1..bd71e4f02 100644
--- a/packages/shared/test/util/effect-flock.test.ts
+++ b/packages/shared/test/util/effect-flock.test.ts
@@ -317,6 +317,7 @@ describe("util.effect-flock", () => {
       })
 
       const result = yield* flock.withLock(Effect.void, "eflock:perm", dir).pipe(Effect.exit)
+      // oxlint-disable-next-line no-base-to-string -- Exit has a useful toString for test assertions
       expect(String(result)).toContain("PermissionDenied")
       yield* Effect.promise(() => fs.chmod(dir, 0o700).then(() => fs.rm(tmp, { recursive: true, force: true })))
     }),
diff --git a/packages/storybook/.storybook/mocks/app/context/language.ts b/packages/storybook/.storybook/mocks/app/context/language.ts
index f75240b9c..c3317ca2e 100644
--- a/packages/storybook/.storybook/mocks/app/context/language.ts
+++ b/packages/storybook/.storybook/mocks/app/context/language.ts
@@ -60,6 +60,7 @@ function render(template: string, params?: Record<string, unknown>) {
   return template.replace(/\{\{([^}]+)\}\}/g, (_, key: string) => {
     const value = params[key.trim()]
     if (value === undefined || value === null) return ""
+    // oxlint-disable-next-line no-base-to-string -- value is Record<string, unknown>, always coerced intentionally
     return String(value)
   })
 }
diff --git a/packages/ui/src/components/file.tsx b/packages/ui/src/components/file.tsx
index fd902b2e0..633b23b70 100644
--- a/packages/ui/src/components/file.tsx
+++ b/packages/ui/src/components/file.tsx
@@ -698,6 +698,7 @@ function TextViewer<T>(props: TextFileProps<T>) {
     if (typeof value === "string") return value
     if (Array.isArray(value)) return value.join("\n")
     if (value == null) return ""
+    // oxlint-disable-next-line no-base-to-string -- file contents cast to unknown, coercion is intentional
     return String(value)
   }
 
@@ -712,11 +713,13 @@ function TextViewer<T>(props: TextFileProps<T>) {
     if (typeof value === "string") return value.length
     if (Array.isArray(value)) {
       return value.reduce(
+        // oxlint-disable-next-line no-base-to-string -- array parts coerced intentionally
         (sum, part) => sum + (typeof part === "string" ? part.length + 1 : String(part).length + 1),
         0,
       )
     }
     if (value == null) return 0
+    // oxlint-disable-next-line no-base-to-string -- file contents cast to unknown, coercion is intentional
     return String(value).length
   })
 
diff --git a/packages/ui/src/components/session-turn.tsx b/packages/ui/src/components/session-turn.tsx
index 2e5f9e38b..75279a90e 100644
--- a/packages/ui/src/components/session-turn.tsx
+++ b/packages/ui/src/components/session-turn.tsx
@@ -313,6 +313,7 @@ export function SessionTurn(
     const msg = error()?.data?.message
     if (typeof msg === "string") return unwrap(msg)
     if (msg === undefined || msg === null) return ""
+    // oxlint-disable-next-line no-base-to-string -- msg is unknown from error data, coercion is intentional
     return unwrap(String(msg))
   })
 
diff --git a/packages/web/src/components/share/part.tsx b/packages/web/src/components/share/part.tsx
index c7d177df7..34cfe3f42 100644
--- a/packages/web/src/components/share/part.tsx
+++ b/packages/web/src/components/share/part.tsx
@@ -730,7 +730,13 @@ export function FallbackTool(props: ToolProps) {
             <>
               <div></div>
               <div>{arg[0]}</div>
-              <div>{String(arg[1] ?? "")}</div>
+              <div>
+                {typeof arg[1] === "string" || typeof arg[1] === "number" || typeof arg[1] === "boolean"
+                  ? String(arg[1])
+                  : arg[1] == null
+                    ? ""
+                    : JSON.stringify(arg[1])}
+              </div>
             </>
           )}
         </For>
-- 
cgit v1.2.3

