diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts
index 355718b6bf..1ad3e9e4fa 100644
--- a/packages/opencode/src/agent/agent.ts
+++ b/packages/opencode/src/agent/agent.ts
@@ -94,6 +94,7 @@ export const layer = Layer.effect(
question: "deny",
plan_enter: "deny",
plan_exit: "deny",
+ edit: "ask",
// mirrors github.com/github/gitignore Node.gitignore pattern for .env files
read: {
"*": "allow",
diff --git a/packages/opencode/src/cli/cmd/run.ts b/packages/opencode/src/cli/cmd/run.ts
index 0874beee16..ed962ffa51 100644
--- a/packages/opencode/src/cli/cmd/run.ts
+++ b/packages/opencode/src/cli/cmd/run.ts
@@ -367,6 +367,11 @@ export const RunCommand = cmd({
action: "deny",
pattern: "*",
},
+ {
+ permission: "edit",
+ action: "allow",
+ pattern: "*",
+ },
]
function title() {
diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx
index 1429e53195..e7f9956608 100644
--- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx
+++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx
@@ -106,6 +106,7 @@ export function Prompt(props: PromptProps) {
const renderer = useRenderer()
const { theme, syntax } = useTheme()
const kv = useKV()
+ const [autoaccept, setAutoaccept] = kv.signal<"none" | "edit">("permission_auto_accept", "edit")
const animationsEnabled = createMemo(() => kv.get("animations_enabled", true))
const list = createMemo(() => props.placeholders?.normal ?? [])
const shell = createMemo(() => props.placeholders?.shell ?? [])
@@ -228,6 +229,16 @@ export function Prompt(props: PromptProps) {
command.register(() => {
return [
+ {
+ title: autoaccept() === "none" ? "Enable autoedit" : "Disable autoedit",
+ value: "permission.auto_accept.toggle",
+ search: "toggle permissions",
+ category: "Agent",
+ onSelect: (dialog) => {
+ setAutoaccept(() => (autoaccept() === "none" ? "edit" : "none"))
+ dialog.clear()
+ },
+ },
{
title: "Clear prompt",
value: "prompt.clear",
@@ -1221,11 +1232,14 @@ export function Prompt(props: PromptProps) {
)}
-
-
- {props.right}
-
-
+
+
+
+ autoedit
+
+
+ {props.right}
+
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 dda9a5a8ed..dd261b26f9 100644
--- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx
+++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx
@@ -37,6 +37,7 @@ export interface DialogSelectOption {
title: string
value: T
description?: string
+ search?: string
footer?: JSX.Element | string
category?: string
categoryView?: JSX.Element
@@ -93,8 +94,8 @@ export function DialogSelect(props: DialogSelectProps) {
// users typically search by the item name, and not its category.
const result = fuzzysort
.go(needle, options, {
- keys: ["title", "category"],
- scoreFn: (r) => r[0].score * 2 + r[1].score,
+ keys: ["title", "category", "search"],
+ scoreFn: (r) => r[0].score * 2 + r[1].score + r[2].score,
})
.map((x) => x.obj)
diff --git a/packages/opencode/test/agent/agent.test.ts b/packages/opencode/test/agent/agent.test.ts
index 50a3668f98..c2ed6a1b01 100644
--- a/packages/opencode/test/agent/agent.test.ts
+++ b/packages/opencode/test/agent/agent.test.ts
@@ -224,8 +224,8 @@ test("agent permission config merges with defaults", async () => {
expect(build).toBeDefined()
// Specific pattern is denied
expect(Permission.evaluate("bash", "rm -rf *", build!.permission).action).toBe("deny")
- // Edit still allowed
- expect(evalPerm(build, "edit")).toBe("allow")
+ // Edit still asks (default behavior)
+ expect(evalPerm(build, "edit")).toBe("ask")
},
})
})