Repository navigation
[FEATURE]: Window System as Foundation for UI Plugin Ecosystem #6521
Description
Feature hasn't been suggested before.
- I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
The current OpenCode TUI architecture limits plugins to backend functionality (tools, commands).
Plugins cannot render persistent UI elements like file browsers, git panels, or search results. This document proposes a window system that decouples view rendering from routing, enabling a rich UI plugin ecosystem.
Current Plugin Capabilities
- ✅ Register tools (AI-callable functions)
- ✅ Register commands (slash commands)
- ✅ Emit events
- ❌ Render persistent UI panels
- ❌ Create sidebars or split views
- ❌ Display interactive trees, lists, forms
Plugins can offer IDE-like extensibility
- NERDTree-style file browser - navigate project, open files in context
- Git panel - stage, diff, commit without leaving OpenCode
- Search results pane - persistent results, click to jump
- MCP tool inspector - monitor tool calls in real-time
None of these is possible with single-view routing.
Current Architecture
flowchart TD
RP[RouteProvider] --> SW{route.type?}
SW -->|home| H[Home Component]
SW -->|session| S[Session Component]
Limitations:
- One view at a time
- Route owns the entire screen
- No mechanism for plugins to inject views
- Navigation replaces everything
Proposed Architecture
flowchart TD
subgraph Plugins
P1[File Tree Plugin]
P2[Git Plugin]
end
subgraph ViewRegistry
V1["home → Home"]
V2["session:* → Session"]
V3["plugin:filetree → FileTree"]
V4["plugin:git → GitPanel"]
end
subgraph LayoutProvider
LT[Layout Tree]
end
P1 -->|register| V3
P2 -->|register| V4
LT --> LR[LayoutRenderer]
LR -->|resolve viewID| ViewRegistry
LR --> W1[Window: plugin:filetree]
LR --> W2[Window: session:abc]
LR --> W3[Window: plugin:git]
Layout Tree Structure
graph TD
Root[Split: horizontal]
Root --> Left[Window<br/>viewID: plugin:filetree]
Root --> Right[Split: vertical]
Right --> Top[Window<br/>viewID: session:abc]
Right --> Bottom[Window<br/>viewID: plugin:git]
Plugin View API
Registering a View
// In plugin initialization
import { ViewRegistry, View } from "@opencode/plugin"
// Tree view (file browser, symbol outline)
ViewRegistry.register("my-plugin:files", View.Tree.create({
id: "my-plugin:files",
title: "Project Files",
nodes: [
{ id: "src", label: "src/", icon: "📁", children: [...] },
{ id: "readme", label: "README.md", icon: "📄", children: [] }
]
}))
// List view (search results, command palette)
ViewRegistry.register("my-plugin:search", View.List.create({
id: "my-plugin:search",
title: "Search Results",
items: [...]
}))View Types
| Type | Use Case | Features |
|---|---|---|
| Tree | File browsers, symbol outlines | Hierarchical, expandable nodes |
| List | Search results, fuzzy finders | Flat, searchable, selectable |
| Text | Logs, previews, docs | Styled, scrollable, read-only |
| Form | Settings, input dialogs | Fields, validation, submit |
Opening a Plugin View
// Plugin requests to open its view
opencode.layout.open("my-plugin:files", {
position: "left", // left, right, top, bottom
size: 0.25 // 25% of screen
})// Or user opens via command
/open my-plugin:filesData Flow
sequenceDiagram
participant U as User
participant K as Keybind Handler
participant L as LayoutProvider
participant R as LayoutRenderer
participant V as ViewRegistry
participant C as Component
U->>K: Ctrl+X |
K->>L: splitVertical("home")
L->>L: Update tree state
L->>R: Re-render
R->>V: resolve("home")
V->>R: Home component
R->>C: Render in new pane
User Experience
Keybindings (Vim-style)
| Action | Keybind |
|---|---|
| Split vertical | Ctrl+X | |
| Split horizontal | Ctrl+X - |
| Navigate | Ctrl+X h/j/k/l |
| Close pane | Ctrl+X q |
| Focus plugin view | Ctrl+X 1/2/3... |
Example Layout
┌─────────────┬─────────────────────────────┐
│ File Tree │ Session: "Fix auth bug" │
│ (plugin) │ │
│ │ > Review src/auth.ts │
│ 📁 src/ │ │
│ 📄 auth.ts │ [AI response...] │
│ 📄 user.ts │ │
│ 📁 tests/ │ │
├─────────────┼─────────────────────────────┤
│ Git Status (plugin) │
│ M src/auth.ts [Stage] [Diff] [Revert] │
└───────────────────────────────────────────┘Why Not Alternatives?
| Approach | Problem |
|---|---|
| Modals/dialogs | Block interaction, not persistent, can't reference while typing |
| Fixed sidebars | Not flexible, each sidebar = special case, plugins can't add their own |
| Plugins render anywhere | No consistency, layout conflicts, focus management nightmare |
| Window system | Consistent primitives, user controls layout, plugins just provide content |
Conclusion
The window system transforms OpenCode from a chat application into an extensible platform.
By decoupling views from routing and providing typed view primitives, we enable a plugin ecosystem comparable to Vim, VS Code, or Emacs.
Activity
github-actions commentedon Dec 31, 2025
This issue might be a duplicate of existing issues. Please check:
All three issues are related to improving plugin UI capabilities and creating persistent, interactive UI panels in OpenCode. While this issue proposes a comprehensive window system architecture, the related issues address specific use cases that would benefit from (or complement) this proposal.
Feel free to ignore if this is intentionally a more fundamental/architectural proposal.
ai-llt commentedon Jan 19, 2026
OpenCode 插件 UI 功能请求 - 实际用例 / OpenCode Plugin UI Feature Request - Real Use Cases
我:整个过程是我和LLM共同测试的,我想保留LLM的想法,只做一些小幅度的修改。我手写的部分会特别标注一下。
Me: The entire process was tested by me and the LLM together. I want to preserve the LLM's ideas and only make minor modifications. The parts I wrote by hand will be specially marked.
背景
我们进行了详细的测试,确认了 Issue #6521 中描述的插件 UI 限制。我们开发了一个
edit_replica插件来扩展原生edit工具的功能。我:我最初的想法是每次修改LLM能够看到修改的内容,而不用再去read一次文件提升速度,我不知道你们有没有遇见过edit经常会将代码块代码结构给改坏,这时候单从LSP去提示已经不足以让LLM意识到问题在哪,于是我想:如果LLM能直接看到代码的diff不就能知道问题在哪了吗?也是从这里我意识到显示在TUI面板上的diff结果LLM是看不到的。
Me: My initial idea was that each time the LLM makes modifications, it could see the changes directly without having to read the file again, thereby improving speed. I don't know if you've encountered situations where edits often mess up the structure of code blocks—in such cases, relying solely on LSP hints isn't enough for the LLM to realize where the problem lies. That's when I thought: if the LLM could directly see the code diff, wouldn't it immediately understand the issue? It was from this realization that I understood the diff results displayed on the TUI panel are not visible to the LLM.
我: 于是我想通过插件的方式增强Edit的功能于是发现了一下需求。
Me: So I wanted to enhance Edit's functionality through plugins, and I discovered the following requirements.
测试结果
测试 1: metadata() 方法
结果:
metadata()方法存在且可调用测试 2: TUI Toast
结果:
client.tui结论
确认的限制:
实际用例:edit_replica 插件
我们开发了一个插件来测试diff display的功能:
功能:
代码示例:
当前输出:
问题:
需求
迫切需要: 插件能够显示 UI diff panel
使用场景:
建议的解决方案
基于 Issue #6521 的 Window System 设计,我们建议:
优先级 1:插件 Diff Panel
允许插件注册并显示 diff panel:
优先级 2:简化版 diff display
提供简化的 API 专门用于显示 diff:
建议
支持 Issue #6521 的 Window System 提案,并提供简化的 API 专门用于显示 diff:
ctx.showDiff({
title: "File Modified",
filepath: "src/auth.ts",
diff: unifiedDiff,
position: "right"
})
这将大大提升插件生态系统的实用价值。
感谢官方团队的努力!期待这个功能的实现。
影响
如果实现:
如果不实现:
参考
我们完全支持 Issue #6521 的 Window System 提案,并提供了这个实际用例来说明为什么插件需要 UI 能力。
感谢官方团队的努力!期待这个功能的实现。
github-actions commentedon Mar 27, 2026
To stay organized issues are automatically closed after 90 days of no activity. If the issue is still relevant please open a new one.
prg-04 commentedon Apr 9, 2026
What is the current status of this Window System proposal? Was it implemented? If not, what's the plan?