From 33f7f593eeba84de34c52779a42b24b4edfa652a Mon Sep 17 00:00:00 2001
From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com>
Date: Thu, 30 Apr 2026 22:45:41 -0500
Subject: [PATCH 1/3] fix: tui list jank issue (#25219)
---
.../opencode/src/cli/cmd/tui/component/dialog-provider.tsx | 2 +-
.../src/cli/cmd/tui/component/dialog-session-list.tsx | 2 +-
packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx | 6 +++---
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx
index ebc28847f..d6cbda413 100644
--- a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx
+++ b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx
@@ -51,7 +51,7 @@ export function createDialogProviderOptions() {
}[provider.id],
footer: consoleManaged ? sync.data.console_state.activeOrgName : undefined,
category: provider.id in PROVIDER_PRIORITY ? "Popular" : "Other",
- gutter: connected && onboarded() ? ✓ : undefined,
+ gutter: connected && onboarded() ? () => ✓ : undefined,
async onSelect() {
if (consoleManaged) return
diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx
index 72d60767b..04c6b9945 100644
--- a/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx
+++ b/packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx
@@ -168,7 +168,7 @@ export function DialogSessionList() {
value: x.id,
category,
footer,
- gutter: isWorking ? : undefined,
+ gutter: isWorking ? () => : undefined,
}
})
})
diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx
index b6c937f41..4d68c4430 100644
--- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx
+++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx
@@ -42,7 +42,7 @@ export interface DialogSelectOption {
categoryView?: JSX.Element
disabled?: boolean
bg?: RGBA
- gutter?: JSX.Element
+ gutter?: () => JSX.Element
margin?: JSX.Element
onSelect?: (ctx: DialogContext) => void
}
@@ -407,7 +407,7 @@ function Option(props: {
active?: boolean
current?: boolean
footer?: JSX.Element | string
- gutter?: JSX.Element
+ gutter?: () => JSX.Element
onMouseOver?: () => void
}) {
const { theme } = useTheme()
@@ -422,7 +422,7 @@ function Option(props: {
- {props.gutter}
+ {props.gutter?.()}
Date: Thu, 30 Apr 2026 23:47:15 -0400
Subject: [PATCH 2/3] Preapprove agent tmp directory access (#25226)
---
packages/core/src/global.ts | 5 +++++
packages/opencode/src/agent/agent.ts | 6 +++++-
packages/opencode/src/tool/bash.ts | 2 ++
packages/opencode/src/tool/bash.txt | 2 ++
4 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/packages/core/src/global.ts b/packages/core/src/global.ts
index 42e0f1030..1acc3f47f 100644
--- a/packages/core/src/global.ts
+++ b/packages/core/src/global.ts
@@ -11,6 +11,7 @@ const data = path.join(xdgData!, app)
const cache = path.join(xdgCache!, app)
const config = path.join(xdgConfig!, app)
const state = path.join(xdgState!, app)
+const tmp = path.join(os.tmpdir(), app)
const paths = {
get home() {
@@ -22,6 +23,7 @@ const paths = {
cache,
config,
state,
+ tmp,
}
export const Path = paths
@@ -32,6 +34,7 @@ await Promise.all([
fs.mkdir(Path.data, { recursive: true }),
fs.mkdir(Path.config, { recursive: true }),
fs.mkdir(Path.state, { recursive: true }),
+ fs.mkdir(Path.tmp, { recursive: true }),
fs.mkdir(Path.log, { recursive: true }),
fs.mkdir(Path.bin, { recursive: true }),
])
@@ -44,6 +47,7 @@ export interface Interface {
readonly cache: string
readonly config: string
readonly state: string
+ readonly tmp: string
readonly bin: string
readonly log: string
}
@@ -55,6 +59,7 @@ export function make(input: Partial = {}): Interface {
cache: Path.cache,
config: Flag.OPENCODE_CONFIG_DIR ?? Path.config,
state: Path.state,
+ tmp: Path.tmp,
bin: Path.bin,
log: Path.log,
...input,
diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts
index 2a090b0ee..b38b0cc5d 100644
--- a/packages/opencode/src/agent/agent.ts
+++ b/packages/opencode/src/agent/agent.ts
@@ -81,7 +81,11 @@ export const layer = Layer.effect(
Effect.fn("Agent.state")(function* (ctx) {
const cfg = yield* config.get()
const skillDirs = yield* skill.dirs()
- const whitelistedDirs = [Truncate.GLOB, ...skillDirs.map((dir) => path.join(dir, "*"))]
+ const whitelistedDirs = [
+ Truncate.GLOB,
+ path.join(Global.Path.tmp, "*"),
+ ...skillDirs.map((dir) => path.join(dir, "*")),
+ ]
const defaults = Permission.fromConfig({
"*": "allow",
diff --git a/packages/opencode/src/tool/bash.ts b/packages/opencode/src/tool/bash.ts
index c50b259f7..fe3e45d66 100644
--- a/packages/opencode/src/tool/bash.ts
+++ b/packages/opencode/src/tool/bash.ts
@@ -14,6 +14,7 @@ import { AppFileSystem } from "@opencode-ai/core/filesystem"
import { fileURLToPath } from "url"
import { Config } from "@/config/config"
import { Flag } from "@opencode-ai/core/flag/flag"
+import { Global } from "@opencode-ai/core/global"
import { Shell } from "@/shell/shell"
import { BashArity } from "@/permission/arity"
@@ -587,6 +588,7 @@ export const BashTool = Tool.define(
return {
description: DESCRIPTION.replaceAll("${directory}", instance.directory)
+ .replaceAll("${tmp}", Global.Path.tmp)
.replaceAll("${os}", process.platform)
.replaceAll("${shell}", name)
.replaceAll("${chaining}", chain)
diff --git a/packages/opencode/src/tool/bash.txt b/packages/opencode/src/tool/bash.txt
index c2fe87379..04e935fe7 100644
--- a/packages/opencode/src/tool/bash.txt
+++ b/packages/opencode/src/tool/bash.txt
@@ -4,6 +4,8 @@ Be aware: OS: ${os}, Shell: ${shell}
All commands run in the current working directory by default. Use the `workdir` parameter if you need to run a command in a different directory. AVOID using `cd && ` patterns - use `workdir` instead.
+Use `${tmp}` for temporary work outside the workspace. This directory is pre-approved for external directory access.
+
IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead.
Before executing the command, please follow these steps:
From 3615d8e226a5dae909139d306e2a684a92680ccf Mon Sep 17 00:00:00 2001
From: Dax Raad
Date: Thu, 30 Apr 2026 23:48:48 -0400
Subject: [PATCH 3/3] core: clarify that temp directory already exists for AI
agents
The bash tool description now explicitly states that the temp directory has already been created and exists, preventing agents from unnecessarily trying to create it before use.
---
packages/opencode/src/tool/bash.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/opencode/src/tool/bash.txt b/packages/opencode/src/tool/bash.txt
index 04e935fe7..a131ed7e6 100644
--- a/packages/opencode/src/tool/bash.txt
+++ b/packages/opencode/src/tool/bash.txt
@@ -4,7 +4,7 @@ Be aware: OS: ${os}, Shell: ${shell}
All commands run in the current working directory by default. Use the `workdir` parameter if you need to run a command in a different directory. AVOID using `cd && ` patterns - use `workdir` instead.
-Use `${tmp}` for temporary work outside the workspace. This directory is pre-approved for external directory access.
+Use `${tmp}` for temporary work outside the workspace. This directory has already been created, already exists, and is pre-approved for external directory access.
IMPORTANT: This tool is for terminal operations like git, npm, docker, etc. DO NOT use it for file operations (reading, writing, editing, searching, finding files) - use the specialized tools for this instead.