diff --git a/packages/tui/src/feature-plugins/builtins.ts b/packages/tui/src/feature-plugins/builtins.ts
index b67923f3c5d1..1295062a8ba4 100644
--- a/packages/tui/src/feature-plugins/builtins.ts
+++ b/packages/tui/src/feature-plugins/builtins.ts
@@ -6,6 +6,7 @@ import SidebarFiles from "./sidebar/files"
import SidebarFooter from "./sidebar/footer"
import SidebarLsp from "./sidebar/lsp"
import SidebarMcp from "./sidebar/mcp"
+import SidebarSubagents from "./sidebar/subagents"
import SidebarTodo from "./sidebar/todo"
import DiffViewer from "./system/diff-viewer"
import Notifications from "./system/notifications"
@@ -25,6 +26,7 @@ export function createBuiltinPlugins(options: { experimentalEventSystem: boolean
SidebarContext,
SidebarMcp,
SidebarLsp,
+ SidebarSubagents,
SidebarTodo,
SidebarFiles,
SidebarFooter,
diff --git a/packages/tui/src/feature-plugins/sidebar/subagents.tsx b/packages/tui/src/feature-plugins/sidebar/subagents.tsx
new file mode 100644
index 000000000000..c39474175282
--- /dev/null
+++ b/packages/tui/src/feature-plugins/sidebar/subagents.tsx
@@ -0,0 +1,82 @@
+import type { TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui"
+import type { Session } from "@opencode-ai/sdk/v2"
+import { createMemo, For, Match, Show, Switch } from "solid-js"
+import { useSync } from "../../context/sync"
+import { collectSubtree } from "../../routes/session"
+import type { BuiltinTuiPlugin } from "../builtins"
+
+const id = "internal:sidebar-subagents"
+
+function title(item: Session) {
+ const value = item.title?.replace(/\s*\(@[^)]* subagent\)\s*$/, "").trim()
+ if (!value) return item.id.slice(0, 8)
+ return value.length > 26 ? `${value.slice(0, 25)}...` : value
+}
+
+function View(props: { api: TuiPluginApi; sessionID: string }) {
+ const theme = () => props.api.theme.current
+ const sync = useSync()
+ // The whole subagent subtree (nested subagents included), derived reactively from
+ // the store — no resource or manual event subscriptions needed. Exclude the root.
+ const children = createMemo(() =>
+ collectSubtree(sync.data.session, props.sessionID)
+ .filter((item) => item.id !== props.sessionID)
+ .toSorted((a, b) => a.time.created - b.time.created),
+ )
+ const running = createMemo(() => children().filter((item) => sync.data.session_status[item.id]?.type !== "idle"))
+ const idle = createMemo(() => children().length - running().length)
+
+ return (
+ 0}>
+
+
+ Subagents{" "}
+ 0 ? theme().warning : theme().textMuted }}>
+
+ 0}>
+ {running().length} running{idle() > 0 ? `, ${idle()} done` : ""}
+
+ 0}>{idle()} done
+
+
+
+
+ {(item) => {
+ const active = () => sync.data.session_status[item.id]?.type !== "idle"
+ return (
+
+
+ {active() ? "•" : "✓"}
+
+
+ {title(item)}
+
+
+ )
+ }}
+
+ 5}>
+ +{children().length - 5} more
+
+
+
+ )
+}
+
+const tui: TuiPlugin = async (api) => {
+ api.slots.register({
+ order: 150,
+ slots: {
+ sidebar_content(_ctx, props) {
+ return
+ },
+ },
+ })
+}
+
+const plugin: BuiltinTuiPlugin = {
+ id,
+ tui,
+}
+
+export default plugin