diff --git a/packages/opencode/src/cli/cmd/tui/app.tsx b/packages/opencode/src/cli/cmd/tui/app.tsx index 42c5b413d..8219939f0 100644 --- a/packages/opencode/src/cli/cmd/tui/app.tsx +++ b/packages/opencode/src/cli/cmd/tui/app.tsx @@ -398,10 +398,52 @@ function App() { slash: { name: "mcps", }, + keybind: "mcp_toggle", onSelect: () => { dialog.replace(() => ) }, }, + ...Array.from({ length: 10 }, (_, i) => { + const slot = i + 1 + return { + title: `Toggle MCP slot ${slot}`, + value: `mcp.toggle.${slot}`, + category: "Agent", + keybind: `mcp_toggle_${slot}` as keyof typeof sync.data.config.keybinds, + hidden: true, + onSelect: async () => { + const mcpNames = Object.keys(sync.data.mcp).sort() + const mcpName = mcpNames[i] + if (!mcpName) { + toast.show({ + variant: "warning", + message: `No MCP configured in slot ${slot}`, + duration: 2000, + }) + return + } + try { + await local.mcp.toggle(mcpName) + const status = await sdk.client.mcp.status() + if (status.data) { + sync.set("mcp", status.data) + } + const isEnabled = local.mcp.isEnabled(mcpName) + toast.show({ + variant: "info", + message: `${mcpName}: ${isEnabled ? "enabled" : "disabled"}`, + duration: 2000, + }) + } catch (error) { + toast.show({ + variant: "error", + message: `Failed to toggle ${mcpName}: ${error}`, + duration: 3000, + }) + } + }, + } + }), { title: "Agent cycle", value: "agent.cycle", @@ -520,6 +562,7 @@ function App() { title: "Toggle console", category: "System", value: "app.console", + keybind: "console_toggle", onSelect: (dialog) => { renderer.console.toggle() dialog.clear() diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx index cacc40e1a..1ab258e7d 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/index.tsx @@ -151,7 +151,7 @@ export function Session() { const [showDetails, setShowDetails] = kv.signal("tool_details_visibility", true) const [showAssistantMetadata, setShowAssistantMetadata] = kv.signal("assistant_metadata_visibility", true) const [showScrollbar, setShowScrollbar] = kv.signal("scrollbar_visible", false) - const [diffWrapMode] = kv.signal<"word" | "none">("diff_wrap_mode", "word") + const [diffWrapMode, setDiffWrapMode] = kv.signal<"word" | "none">("diff_wrap_mode", "word") const [animationsEnabled, setAnimationsEnabled] = kv.signal("animations_enabled", true) const wide = createMemo(() => dimensions().width > 120) @@ -542,6 +542,7 @@ export function Session() { name: "timestamps", aliases: ["toggle-timestamps"], }, + keybind: "timestamps_toggle", onSelect: (dialog) => { setTimestamps((prev) => (prev === "show" ? "hide" : "show")) dialog.clear() @@ -555,11 +556,25 @@ export function Session() { name: "thinking", aliases: ["toggle-thinking"], }, + keybind: "thinking_toggle", onSelect: (dialog) => { setShowThinking((prev) => !prev) dialog.clear() }, }, + { + title: "Toggle diff wrapping", + value: "session.toggle.diffwrap", + category: "Session", + slash: { + name: "diffwrap", + }, + keybind: "diffwrap_toggle", + onSelect: (dialog) => { + setDiffWrapMode((prev) => (prev === "word" ? "none" : "word")) + dialog.clear() + }, + }, { title: showDetails() ? "Hide tool details" : "Show tool details", value: "session.toggle.actions", diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index c70894ffe..0781dbaa2 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -810,6 +810,21 @@ export namespace Config { sidebar_toggle: z.string().optional().default("b").describe("Toggle sidebar"), scrollbar_toggle: z.string().optional().default("none").describe("Toggle session scrollbar"), username_toggle: z.string().optional().default("none").describe("Toggle username visibility"), + console_toggle: z.string().optional().default("none").describe("Toggle console"), + mcp_toggle: z.string().optional().default("none").describe("Toggle MCP dialog"), + mcp_toggle_1: z.string().optional().default("none").describe("Toggle MCP slot 1"), + mcp_toggle_2: z.string().optional().default("none").describe("Toggle MCP slot 2"), + mcp_toggle_3: z.string().optional().default("none").describe("Toggle MCP slot 3"), + mcp_toggle_4: z.string().optional().default("none").describe("Toggle MCP slot 4"), + mcp_toggle_5: z.string().optional().default("none").describe("Toggle MCP slot 5"), + mcp_toggle_6: z.string().optional().default("none").describe("Toggle MCP slot 6"), + mcp_toggle_7: z.string().optional().default("none").describe("Toggle MCP slot 7"), + mcp_toggle_8: z.string().optional().default("none").describe("Toggle MCP slot 8"), + mcp_toggle_9: z.string().optional().default("none").describe("Toggle MCP slot 9"), + mcp_toggle_10: z.string().optional().default("none").describe("Toggle MCP slot 10"), + timestamps_toggle: z.string().optional().default("none").describe("Toggle timestamps visibility"), + thinking_toggle: z.string().optional().default("none").describe("Toggle thinking visibility"), + diffwrap_toggle: z.string().optional().default("none").describe("Toggle diff wrapping"), status_view: z.string().optional().default("s").describe("View status"), session_export: z.string().optional().default("x").describe("Export session to editor"), session_new: z.string().optional().default("n").describe("Create a new session"), @@ -845,6 +860,7 @@ export namespace Config { messages_previous: z.string().optional().default("none").describe("Navigate to previous message"), messages_last_user: z.string().optional().default("none").describe("Navigate to last user message"), messages_copy: z.string().optional().default("y").describe("Copy message"), + session_copy: z.string().optional().default("none").describe("Copy session transcript"), messages_undo: z.string().optional().default("u").describe("Undo message"), messages_redo: z.string().optional().default("r").describe("Redo message"), messages_toggle_conceal: z diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 2e8208697..d1df83a16 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -965,6 +965,66 @@ export type KeybindsConfig = { * Toggle username visibility */ username_toggle?: string + /** + * Toggle console + */ + console_toggle?: string + /** + * Toggle MCP dialog + */ + mcp_toggle?: string + /** + * Toggle MCP slot 1 + */ + mcp_toggle_1?: string + /** + * Toggle MCP slot 2 + */ + mcp_toggle_2?: string + /** + * Toggle MCP slot 3 + */ + mcp_toggle_3?: string + /** + * Toggle MCP slot 4 + */ + mcp_toggle_4?: string + /** + * Toggle MCP slot 5 + */ + mcp_toggle_5?: string + /** + * Toggle MCP slot 6 + */ + mcp_toggle_6?: string + /** + * Toggle MCP slot 7 + */ + mcp_toggle_7?: string + /** + * Toggle MCP slot 8 + */ + mcp_toggle_8?: string + /** + * Toggle MCP slot 9 + */ + mcp_toggle_9?: string + /** + * Toggle MCP slot 10 + */ + mcp_toggle_10?: string + /** + * Toggle timestamps visibility + */ + timestamps_toggle?: string + /** + * Toggle thinking visibility + */ + thinking_toggle?: string + /** + * Toggle diff wrapping + */ + diffwrap_toggle?: string /** * View status */ @@ -1073,6 +1133,10 @@ export type KeybindsConfig = { * Copy message */ messages_copy?: string + /** + * Copy session transcript + */ + session_copy?: string /** * Undo message */