diff --git a/.opencode/commands/browser-setup.md b/.opencode/commands/browser-setup.md
new file mode 100644
index 00000000..36c4a01f
--- /dev/null
+++ b/.opencode/commands/browser-setup.md
@@ -0,0 +1,12 @@
+---
+name: browser-setup
+description: Guide user through Chrome browser automation setup
+---
+
+Help the user set up browser automation.
+
+1. Ask: "Do you have Chrome installed on this computer?"
+2. If they say no or are unsure, guide them to install Chrome
+3. If yes, check if browser MCP/plugin is available
+4. If not available, guide them to install the OpenCode browser extension
+5. Once setup is complete, offer to run a simple first task (e.g., "Let's try opening a webpage")
diff --git a/packages/app/pr/browser-entry-button.md b/packages/app/pr/browser-entry-button.md
new file mode 100644
index 00000000..4d95f033
--- /dev/null
+++ b/packages/app/pr/browser-entry-button.md
@@ -0,0 +1,114 @@
+# Browser Entry Button
+
+**Branch:** `feat/browser-entry-button`
+**Priority:** P1
+
+---
+
+## Goal
+
+Add a single entry button in the empty chat state that triggers browser automation setup via OpenCode command.
+
+---
+
+## Implementation
+
+### Location
+`packages/app/src/app/pages/session.tsx` L1025-1037
+
+### Code references
+- Empty state render: `packages/app/src/app/pages/session.tsx:1039-1049`
+- Command runner used by slash commands: `packages/app/src/app/pages/session.tsx:645-663` (`runOpenCodeCommand`)
+- Command registry wiring: `packages/app/src/app/pages/session.tsx:881-892`
+- Programmatic command execution: `packages/app/src/app/command-state.ts:293-313`
+- `.opencode/commands` loader: `packages/app/src/app/command-state.ts:334`
+- Existing button pattern: `packages/app/src/app/pages/dashboard.tsx:557` (`onClick={() => props.runCommand(command)}`)
+- Command write API (desktop): `packages/app/src/app/lib/tauri.ts:223` (`opencodeCommandWrite`)
+- Frontmatter parser: `packages/app/src/app/utils/index.ts:271` (`parseTemplateFrontmatter`)
+
+### Current empty state
+```tsx
+
+
+
Start a conversation
+
Describe what you want to do...
+
+
+```
+
+### Add button
+```tsx
+
+
+
+
+
+
+
What do you want to do?
+
+ Pick a starting point or just type below.
+
+
+
+
+
+
+
+```
+
+**Why `runOpenCodeCommand`**
+- It handles `$ARGUMENTS` and opens the command run modal when needed (`session.tsx:645-663`)
+- Keeps behavior identical to slash commands
+
+### Create OpenCode command
+File: `.opencode/commands/browser-setup.md`
+
+**App template source:** `packages/app/src/app/data/commands/browser-setup.md`
+
+If the command is missing in the active workspace, the button auto-writes it via `opencodeCommandWrite` (desktop only) before running.
+
+```markdown
+---
+name: browser-setup
+description: Guide user through Chrome browser automation setup
+---
+
+Help the user set up browser automation.
+
+1. Ask: "Do you have Chrome installed on this computer?"
+2. If they say no or are unsure, guide them to install Chrome
+3. If yes, check if browser MCP/plugin is available
+4. If not available, guide them to install the OpenCode browser extension
+5. Once setup is complete, offer to run a simple first task (e.g., "Let's try opening a webpage")
+```
+
+---
+
+## Flow (handled by LLM)
+
+1. User clicks "Automate your browser"
+2. Command triggers, LLM asks: "Do you have Chrome installed?"
+3. User answers Yes/No
+4. LLM guides through extension install if needed
+5. LLM offers first browser task
+
+---
+
+## NOT doing
+
+- Custom guided prompts in the UI
+- Multiple entry buttons (start with one)
+- Hardcoded installation scripts
diff --git a/packages/app/src/app/data/commands/browser-setup.md b/packages/app/src/app/data/commands/browser-setup.md
new file mode 100644
index 00000000..36c4a01f
--- /dev/null
+++ b/packages/app/src/app/data/commands/browser-setup.md
@@ -0,0 +1,12 @@
+---
+name: browser-setup
+description: Guide user through Chrome browser automation setup
+---
+
+Help the user set up browser automation.
+
+1. Ask: "Do you have Chrome installed on this computer?"
+2. If they say no or are unsure, guide them to install Chrome
+3. If yes, check if browser MCP/plugin is available
+4. If not available, guide them to install the OpenCode browser extension
+5. Once setup is complete, offer to run a simple first task (e.g., "Let's try opening a webpage")
diff --git a/packages/app/src/app/pages/session.tsx b/packages/app/src/app/pages/session.tsx
index afe22c9e..a97c10e3 100644
--- a/packages/app/src/app/pages/session.tsx
+++ b/packages/app/src/app/pages/session.tsx
@@ -35,6 +35,9 @@ import WorkspaceChip from "../components/workspace-chip";
import ProviderAuthModal from "../components/provider-auth-modal";
import StatusBar from "../components/status-bar";
import type { OpenworkServerStatus } from "../lib/openwork-server";
+import browserSetupCommandTemplate from "../data/commands/browser-setup.md?raw";
+import { opencodeCommandWrite } from "../lib/tauri";
+import { isTauriRuntime, parseTemplateFrontmatter } from "../utils";
import MessageList from "../components/session/message-list";
import Composer from "../components/session/composer";
@@ -147,6 +150,57 @@ export default function SessionView(props: SessionViewProps) {
const agentLabel = createMemo(() => props.selectedSessionAgent ?? "Default agent");
+ const buildBrowserSetupCommand = () => {
+ const parsed = parseTemplateFrontmatter(browserSetupCommandTemplate);
+ const name = parsed?.data.name?.trim() || "browser-setup";
+ const description =
+ parsed?.data.description?.trim() || "Guide user through Chrome browser automation setup";
+ const template = parsed?.body?.trim() || browserSetupCommandTemplate.trim();
+
+ return { name, description, template };
+ };
+
+ const ensureBrowserSetupCommand = async (): Promise => {
+ const existing = props.commands.find((item) => item.name === "browser-setup");
+ if (existing) return existing;
+
+ if (props.activeWorkspaceDisplay.workspaceType === "remote") {
+ setCommandToast("Browser setup command is only available in local workspaces.");
+ return null;
+ }
+
+ if (!isTauriRuntime()) {
+ setCommandToast("Browser setup is available in the desktop app.");
+ return null;
+ }
+
+ const root = props.activeWorkspaceDisplay.path?.trim() ?? "";
+ if (!root) {
+ setCommandToast("Pick a workspace folder to install the command.");
+ return null;
+ }
+
+ try {
+ const draft = buildBrowserSetupCommand();
+ await opencodeCommandWrite({
+ scope: "workspace",
+ projectDir: root,
+ command: draft,
+ });
+
+ return {
+ name: draft.name,
+ description: draft.description,
+ template: draft.template,
+ scope: "workspace",
+ };
+ } catch (error) {
+ const message = error instanceof Error ? error.message : "Failed to install browser setup command";
+ setCommandToast(message);
+ return null;
+ }
+ };
+
const loadAgentOptions = async (force = false) => {
if (agentPickerBusy()) return agentOptions();
if (agentPickerReady() && !force) return agentOptions();
@@ -1042,11 +1096,27 @@ export default function SessionView(props: SessionViewProps) {
-
Start a conversation
+
What do you want to do?
- Describe what you want to do, and OpenWork will take it from there.
+ Pick a starting point or just type below.