diff --git a/packages/opencode/src/cli/cmd/tui/component/did-you-know.tsx b/packages/opencode/src/cli/cmd/tui/component/did-you-know.tsx
new file mode 100644
index 00000000000..36bf174c117
--- /dev/null
+++ b/packages/opencode/src/cli/cmd/tui/component/did-you-know.tsx
@@ -0,0 +1,85 @@
+import { createMemo, createSignal, For } from "solid-js"
+import { useTheme } from "@tui/context/theme"
+import { useKeybind } from "@tui/context/keybind"
+import { TIPS } from "./tips"
+import { EmptyBorder } from "./border"
+
+type TipPart = { text: string; highlight: boolean }
+
+function parseTip(tip: string): TipPart[] {
+ const parts: TipPart[] = []
+ const regex = /\{highlight\}(.*?)\{\/highlight\}/g
+ let lastIndex = 0
+ let match
+
+ while ((match = regex.exec(tip)) !== null) {
+ if (match.index > lastIndex) {
+ parts.push({ text: tip.slice(lastIndex, match.index), highlight: false })
+ }
+ parts.push({ text: match[1], highlight: true })
+ lastIndex = regex.lastIndex
+ }
+
+ if (lastIndex < tip.length) {
+ parts.push({ text: tip.slice(lastIndex), highlight: false })
+ }
+
+ return parts
+}
+
+const [tipIndex, setTipIndex] = createSignal(Math.floor(Math.random() * TIPS.length))
+
+export function randomizeTip() {
+ setTipIndex(Math.floor(Math.random() * TIPS.length))
+}
+
+const BOX_WIDTH = 42
+const TITLE = " 🅘 Did you know? "
+
+export function DidYouKnow() {
+ const { theme } = useTheme()
+ const keybind = useKeybind()
+
+ const tipParts = createMemo(() => parseTip(TIPS[tipIndex()]))
+
+ const dashes = createMemo(() => {
+ // â•─ + title + ─...─ + â•® = BOX_WIDTH
+ // 1 + 1 + title.length + dashes + 1 = BOX_WIDTH
+ return Math.max(0, BOX_WIDTH - 2 - TITLE.length - 1)
+ })
+
+ return (
+
+
+ â•─
+ {TITLE}
+ {"─".repeat(dashes())}╮
+
+
+
+
+
+ {(part) => {part.text}}
+
+
+
+
+
+
+ {keybind.print("tips_toggle")}
+ hide tips
+
+
+
+ )
+}
diff --git a/packages/opencode/src/cli/cmd/tui/component/tips.ts b/packages/opencode/src/cli/cmd/tui/component/tips.ts
new file mode 100644
index 00000000000..be329076c0a
--- /dev/null
+++ b/packages/opencode/src/cli/cmd/tui/component/tips.ts
@@ -0,0 +1,103 @@
+export const TIPS = [
+ "Type {highlight}@{/highlight} followed by a filename to fuzzy search and attach files to your prompt.",
+ "Start a message with {highlight}!{/highlight} to run shell commands directly (e.g., {highlight}!ls -la{/highlight}).",
+ "Press {highlight}Tab{/highlight} to cycle between Build (full access) and Plan (read-only) agents.",
+ "Use {highlight}/undo{/highlight} to revert the last message and any file changes made by OpenCode.",
+ "Use {highlight}/redo{/highlight} to restore previously undone messages and file changes.",
+ "Run {highlight}/share{/highlight} to create a public link to your conversation at opencode.ai.",
+ "Drag and drop images into the terminal to add them as context for your prompts.",
+ "Press {highlight}Ctrl+V{/highlight} to paste images from your clipboard directly into the prompt.",
+ "Press {highlight}Ctrl+X E{/highlight} or {highlight}/editor{/highlight} to compose messages in your external editor.",
+ "Run {highlight}/init{/highlight} to auto-generate project rules based on your codebase structure.",
+ "Run {highlight}/models{/highlight} or {highlight}Ctrl+X M{/highlight} to see and switch between available AI models.",
+ "Use {highlight}/theme{/highlight} or {highlight}Ctrl+X T{/highlight} to preview and switch between 50+ built-in themes.",
+ "Press {highlight}Ctrl+X N{/highlight} or {highlight}/new{/highlight} to start a fresh conversation session.",
+ "Use {highlight}/sessions{/highlight} or {highlight}Ctrl+X L{/highlight} to list and continue previous conversations.",
+ "Run {highlight}/compact{/highlight} to summarize long sessions when approaching context limits.",
+ "Press {highlight}Ctrl+X X{/highlight} or {highlight}/export{/highlight} to save the conversation as Markdown.",
+ "Press {highlight}Ctrl+X Y{/highlight} to copy the assistant's last message to clipboard.",
+ "Press {highlight}Ctrl+P{/highlight} to see all available actions and commands.",
+ "Run {highlight}/connect{/highlight} to add API keys for 75+ supported LLM providers.",
+ "The default leader key is {highlight}Ctrl+X{/highlight}; combine with other keys for quick actions.",
+ "Press {highlight}F2{/highlight} to quickly switch between recently used models.",
+ "Press {highlight}Ctrl+X B{/highlight} to show/hide the sidebar panel.",
+ "Use {highlight}PageUp{/highlight}/{highlight}PageDown{/highlight} to navigate through conversation history.",
+ "Press {highlight}Ctrl+G{/highlight} or {highlight}Home{/highlight} to jump to the beginning of the conversation.",
+ "Press {highlight}Ctrl+Alt+G{/highlight} or {highlight}End{/highlight} to jump to the most recent message.",
+ "Press {highlight}Shift+Enter{/highlight} or {highlight}Ctrl+J{/highlight} to add newlines in your prompt.",
+ "Press {highlight}Ctrl+C{/highlight} when typing to clear the input field.",
+ "Press {highlight}Escape{/highlight} to stop the AI mid-response.",
+ "Switch to {highlight}Plan{/highlight} agent to get suggestions without making actual changes.",
+ "Use {highlight}@agent-name{/highlight} in prompts to invoke specialized subagents.",
+ "Press {highlight}Ctrl+X Right/Left{/highlight} to cycle through parent and child sessions.",
+ "Create {highlight}opencode.json{/highlight} in project root for project-specific settings.",
+ "Place settings in {highlight}~/.config/opencode/opencode.json{/highlight} for global config.",
+ "Add {highlight}$schema{/highlight} to your config for autocomplete in your editor.",
+ "Configure {highlight}model{/highlight} in config to set your default model.",
+ "Override any keybind in config via the {highlight}keybinds{/highlight} section.",
+ "Set any keybind to {highlight}none{/highlight} to disable it completely.",
+ "Configure local or remote MCP servers in the {highlight}mcp{/highlight} config section.",
+ "OpenCode auto-handles OAuth for remote MCP servers requiring auth.",
+ "Add {highlight}.md{/highlight} files to {highlight}.opencode/command/{/highlight} to define reusable custom prompts.",
+ "Use {highlight}$ARGUMENTS{/highlight}, {highlight}$1{/highlight}, {highlight}$2{/highlight} in custom commands for dynamic input.",
+ "Use backticks in commands to inject shell output (e.g., {highlight}`git status`{/highlight}).",
+ "Add {highlight}.md{/highlight} files to {highlight}.opencode/agent/{/highlight} for specialized AI personas.",
+ "Configure per-agent permissions for {highlight}edit{/highlight}, {highlight}bash{/highlight}, and {highlight}webfetch{/highlight} tools.",
+ 'Use patterns like {highlight}"git *": "allow"{/highlight} for granular bash permissions.',
+ 'Set {highlight}"rm -rf *": "deny"{/highlight} to block destructive commands.',
+ 'Configure {highlight}"git push": "ask"{/highlight} to require approval before pushing.',
+ "OpenCode auto-formats files using prettier, gofmt, ruff, and more.",
+ 'Set {highlight}"formatter": false{/highlight} in config to disable all auto-formatting.',
+ "Define custom formatter commands with file extensions in config.",
+ "OpenCode uses LSP servers for intelligent code analysis.",
+ "Create {highlight}.ts{/highlight} files in {highlight}.opencode/tool/{/highlight} to define new LLM tools.",
+ "Tool definitions can invoke scripts written in Python, Go, etc.",
+ "Add {highlight}.ts{/highlight} files to {highlight}.opencode/plugin/{/highlight} for event hooks.",
+ "Use plugins to send OS notifications when sessions complete.",
+ "Create a plugin to prevent OpenCode from reading sensitive files.",
+ "Use {highlight}opencode run{/highlight} for non-interactive scripting.",
+ "Use {highlight}opencode run --continue{/highlight} to resume the last session.",
+ "Use {highlight}opencode run -f file.ts{/highlight} to attach files via CLI.",
+ "Use {highlight}--format json{/highlight} for machine-readable output in scripts.",
+ "Run {highlight}opencode serve{/highlight} for headless API access to OpenCode.",
+ "Use {highlight}opencode run --attach{/highlight} to connect to a running server for faster runs.",
+ "Run {highlight}opencode upgrade{/highlight} to update to the latest version.",
+ "Run {highlight}opencode auth list{/highlight} to see all configured providers.",
+ "Run {highlight}opencode agent create{/highlight} for guided agent creation.",
+ "Use {highlight}/opencode{/highlight} in GitHub issues/PRs to trigger AI actions.",
+ "Run {highlight}opencode github install{/highlight} to set up the GitHub workflow.",
+ "Comment {highlight}/opencode fix this{/highlight} on issues to auto-create PRs.",
+ "Comment {highlight}/oc{/highlight} on PR code lines for targeted code reviews.",
+ 'Use {highlight}"theme": "system"{/highlight} to match your terminal\'s colors.',
+ "Create JSON theme files in {highlight}.opencode/themes/{/highlight} directory.",
+ "Themes support dark/light variants for both modes.",
+ "Reference ANSI colors 0-255 in custom themes.",
+ "Use {highlight}{env:VAR_NAME}{/highlight} syntax to reference environment variables in config.",
+ "Use {highlight}{file:path}{/highlight} to include file contents in config values.",
+ "Use {highlight}instructions{/highlight} in config to load additional rules files.",
+ "Set agent {highlight}temperature{/highlight} from 0.0 (focused) to 1.0 (creative).",
+ "Configure {highlight}maxSteps{/highlight} to limit agentic iterations per request.",
+ 'Set {highlight}"tools": {"bash": false}{/highlight} to disable specific tools.',
+ 'Use {highlight}"mcp_*": false{/highlight} to disable all tools from an MCP server.',
+ "Override global tool settings per agent configuration.",
+ 'Set {highlight}"share": "auto"{/highlight} to automatically share all sessions.',
+ 'Set {highlight}"share": "disabled"{/highlight} to prevent any session sharing.',
+ "Run {highlight}/unshare{/highlight} to remove a session from public access.",
+ "Permission {highlight}doom_loop{/highlight} prevents infinite tool call loops.",
+ "Permission {highlight}external_directory{/highlight} protects files outside project.",
+ "Run {highlight}opencode debug config{/highlight} to troubleshoot configuration.",
+ "Use {highlight}--print-logs{/highlight} flag to see detailed logs in stderr.",
+ "Press {highlight}Ctrl+X G{/highlight} or {highlight}/timeline{/highlight} to jump to specific messages.",
+ "Press {highlight}Ctrl+X H{/highlight} to toggle code block visibility in messages.",
+ "Press {highlight}Ctrl+X S{/highlight} or {highlight}/status{/highlight} to see system status info.",
+ "Enable {highlight}tui.scroll_acceleration{/highlight} for smooth macOS-style scrolling.",
+ "Toggle username display in chat via command palette ({highlight}Ctrl+P{/highlight}).",
+ "Run {highlight}docker run -it --rm ghcr.io/sst/opencode{/highlight} for containerized use.",
+ "Use {highlight}/connect{/highlight} with OpenCode Zen for curated, tested models.",
+ "Commit your project's {highlight}AGENTS.md{/highlight} file to Git for team sharing.",
+ "Use {highlight}/review{/highlight} to review uncommitted changes, branches, or PRs.",
+ "Run {highlight}/help{/highlight} or {highlight}Ctrl+X H{/highlight} to show the help dialog.",
+ "Use {highlight}/details{/highlight} to toggle tool execution details visibility.",
+ "Use {highlight}/rename{/highlight} to rename the current session.",
+ "Press {highlight}Ctrl+Z{/highlight} to suspend the terminal and return to your shell.",
+]
diff --git a/packages/opencode/src/cli/cmd/tui/routes/home.tsx b/packages/opencode/src/cli/cmd/tui/routes/home.tsx
index ecdf93c43df..e5d6d15a140 100644
--- a/packages/opencode/src/cli/cmd/tui/routes/home.tsx
+++ b/packages/opencode/src/cli/cmd/tui/routes/home.tsx
@@ -2,23 +2,28 @@ import { Prompt, type PromptRef } from "@tui/component/prompt"
import { createMemo, Match, onMount, Show, Switch } from "solid-js"
import { useTheme } from "@tui/context/theme"
import { Logo } from "../component/logo"
+import { DidYouKnow, randomizeTip } from "../component/did-you-know"
import { Locale } from "@/util/locale"
import { useSync } from "../context/sync"
import { Toast } from "../ui/toast"
import { useArgs } from "../context/args"
import { useDirectory } from "../context/directory"
-import { useRoute, useRouteData } from "@tui/context/route"
+import { useRouteData } from "@tui/context/route"
import { usePromptRef } from "../context/prompt"
import { Installation } from "@/installation"
+import { useKV } from "../context/kv"
+import { useCommandDialog } from "../component/dialog-command"
// TODO: what is the best way to do this?
let once = false
export function Home() {
const sync = useSync()
+ const kv = useKV()
const { theme } = useTheme()
const route = useRouteData("home")
const promptRef = usePromptRef()
+ const command = useCommandDialog()
const mcp = createMemo(() => Object.keys(sync.data.mcp).length > 0)
const mcpError = createMemo(() => {
return Object.values(sync.data.mcp).some((x) => x.status === "failed")
@@ -28,6 +33,27 @@ export function Home() {
return Object.values(sync.data.mcp).filter((x) => x.status === "connected").length
})
+ const isFirstTimeUser = createMemo(() => sync.data.session.length === 0)
+ const tipsHidden = createMemo(() => kv.get("tips_hidden", false))
+ const showTips = createMemo(() => {
+ // Don't show tips for first-time users
+ if (isFirstTimeUser()) return false
+ return !tipsHidden()
+ })
+
+ command.register(() => [
+ {
+ title: tipsHidden() ? "Show tips" : "Hide tips",
+ value: "tips.toggle",
+ keybind: "tips_toggle",
+ category: "System",
+ onSelect: (dialog) => {
+ kv.set("tips_hidden", !tipsHidden())
+ dialog.clear()
+ },
+ },
+ ])
+
const Hint = (
0}>
@@ -50,6 +76,7 @@ export function Home() {
let prompt: PromptRef
const args = useArgs()
onMount(() => {
+ randomizeTip()
if (once) return
if (route.initialPrompt) {
prompt.set(route.initialPrompt)
@@ -77,6 +104,11 @@ export function Home() {
+
+
+
+
+
{directory()}
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index cb93c0ebf2a..ba9d1973025 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -566,6 +566,7 @@ export namespace Config {
session_parent: z.string().optional().default("up").describe("Go to parent session"),
terminal_suspend: z.string().optional().default("ctrl+z").describe("Suspend terminal"),
terminal_title_toggle: z.string().optional().default("none").describe("Toggle terminal title"),
+ tips_toggle: z.string().optional().default("h").describe("Toggle tips on home screen"),
})
.strict()
.meta({
diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts
index c5f11c885fb..6c6fbbf4924 100644
--- a/packages/sdk/js/src/v2/gen/types.gen.ts
+++ b/packages/sdk/js/src/v2/gen/types.gen.ts
@@ -1134,6 +1134,10 @@ export type KeybindsConfig = {
* Toggle terminal title
*/
terminal_title_toggle?: string
+ /**
+ * Toggle tips on home screen
+ */
+ tips_toggle?: string
}
export type AgentConfig = {
diff --git a/packages/ui/src/components/list.css b/packages/ui/src/components/list.css
index 1714b35137a..852bf486c91 100644
--- a/packages/ui/src/components/list.css
+++ b/packages/ui/src/components/list.css
@@ -51,6 +51,24 @@
}
}
}
+
+ > [data-component="icon-button"] {
+ background-color: transparent;
+
+ &:hover:not(:disabled),
+ &:focus:not(:disabled),
+ &:active:not(:disabled) {
+ background-color: transparent;
+ }
+
+ &:hover:not(:disabled) [data-slot="icon-svg"] {
+ color: var(--icon-hover);
+ }
+
+ &:active:not(:disabled) [data-slot="icon-svg"] {
+ color: var(--icon-active);
+ }
+ }
}
[data-slot="list-scroll"] {