You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Opencode requires them to actually implement more robust capabilities around plan mode. Right now, it just seems like a dummy chat.
The Complete Flow (What Actually Happens)
1. User switches to "plan" agent (Tab key or agent selector)
└─ File: opencode/packages/opencode/src/cli/cmd/tui/app.tsx (agent_cycle command)
2. When sending a message with plan agent selected:
└─ File: opencode/packages/opencode/src/session/prompt.ts:1009
└─ insertReminders() injects PROMPT_PLAN text into user message
3. LLM receives message with READ-ONLY constraints
└─ Responds with analysis/planning as regular chat text
└─ If it tries to edit → Permission.ask() with edit:"deny" → Rejected
4. Plans are just text in the chat (no storage, no approval)
5. User manually switches to "build" agent when ready
└─ BUILD_SWITCH prompt injected telling LLM it can now make changes
Adapt Plannotator (existing Claude Code plugin at /Users/ramos/cupcake/cupcake-rego/planning-hook) to work with OpenCode. The goal is to give OpenCode the same interactive plan review experience with visual annotation.
What We Build: OpenCode plugin that bridges to Plannotator's server/UI.
Core Differences: Claude Code vs OpenCode
Aspect
Claude Code
OpenCode
Hook trigger
PermissionRequest on ExitPlanMode
Plugin tool submit_plan
Data input
stdin JSON from hook
Tool args in execute()
Decision output
stdout JSON
Tool return value
Mode switch
Automatic (allow = proceed)
client.tui.executeCommand
Core UX Flow
User activates "plan" agent in OpenCode
↓
Plugin injects planning workflow prompts
↓
Agent explores, plans, calls `submit_plan` tool
↓
Plugin starts Plannotator server with plan markdown
↓
Browser opens → Plannotator UI
↓
User annotates, then clicks Approve or Provide Feedback
↓
┌────────┴────────┐
↓ ↓
APPROVED DENIED
↓ ↓
Tool returns Tool returns
success msg diff feedback
↓ ↓
Plugin switches Agent revises
to "build" agent and resubmits
↓
Agent begins implementation
Directory Structure
/Users/ramos/cupcake/cupcake-rego/planning-hook/
├── apps/
│ ├── hook/ # Claude Code plugin (existing)
│ │ └── server/index.ts # Bun server (adapt for reuse)
│ └── opencode-plugin/ # NEW: OpenCode plugin
│ ├── index.ts # Plugin entry point
│ ├── server.ts # Server adapter
│ └── package.json
├── packages/
│ ├── editor/ # Shared - App.tsx (no changes)
│ └── ui/ # Shared - components (no changes)
└── package.json # Add opencode-plugin to workspaces
Implementation Plan
Step 1: Create Plugin Scaffold
Files to create:
apps/opencode-plugin/package.json
apps/opencode-plugin/index.ts
// apps/opencode-plugin/index.tsimport{typePlugin,tool}from"@opencode-ai/plugin"exportconstPlannotatorPlugin: Plugin=async(ctx)=>{return{tool: {submit_plan: tool({description: "Submit your completed plan for interactive user review",args: {plan: tool.schema.string().describe("Complete plan in markdown"),summary: tool.schema.string().describe("Brief summary"),},asyncexecute(args,context){// Step 4 implementation},}),},}}
Step 2: Adapt Server for Function-Based Invocation
asyncexecute(args,context){// Start serverconst{ port, waitForDecision }=awaitstartPlannotatorServer(args.plan)// Open browserawaitopenBrowser(`http://localhost:${port}`)// Wait for user decision (blocks until approve/deny)constdecision=awaitwaitForDecision()if(decision.approved){// Switch to build modeawaitctx.client.tui.executeCommand({body: {command: "agent_cycle"}})return"Plan approved! Switching to build mode. Proceed with implementation."}else{return`Plan needs revision. User feedback:\n\n${decision.feedback}\n\nRevise and call submit_plan again.`}}
Step 5: Add System Prompt Injection (Optional Enhancement)
"experimental.chat.system.transform": async(input,output)=>{output.system.push(`When in plan mode, create a comprehensive plan then call submit_plan.The user will review your plan visually and can annotate with feedback.If rejected, revise based on feedback and resubmit. `)}
Step 6: Build Configuration
Add to package.json workspaces, create Vite config to build single-file HTML:
// apps/opencode-plugin/vite.config.ts// Similar to apps/hook/vite.config.ts// Outputs dist/index.html with embedded JS/CSS
Verification Checklist
#
Test
Command/Action
Expected
1
Plugin loads
Start OpenCode with plugin
No errors, tool registered
2
Tool available
Agent lists tools
submit_plan appears
3
Server starts
Call submit_plan
Browser opens Plannotator
4
Plan displays
View UI
Markdown rendered correctly
5
Annotations work
Select text, add comment
Annotation appears in sidebar
6
Approve flow
Click Approve
Tool returns success, mode switches
7
Deny flow
Annotate + Provide Feedback
Tool returns diff feedback
8
Revision loop
Agent receives feedback
Agent revises and resubmits
Files to Create
File
Lines (est)
Purpose
apps/opencode-plugin/package.json
15
Package config
apps/opencode-plugin/index.ts
60
Plugin entry + submit_plan tool
apps/opencode-plugin/server.ts
80
Adapted Bun server
apps/opencode-plugin/vite.config.ts
30
Build config
Files to Reference (Read-Only)
File
Purpose
apps/hook/server/index.ts
Server logic to adapt
apps/hook/vite.config.ts
Build config template
packages/editor/App.tsx
UI entry (reuse as-is)
packages/ui/utils/parser.ts
exportDiff() for feedback
Decisions Made
Shared build: OpenCode plugin will import the built HTML from apps/hook/dist/index.html - single source of truth, no duplication.
Detecting plan agent: Will investigate during implementation - may need to check context or use event hook.
Implementation Order
Create apps/opencode-plugin/ directory structure
Create package.json with @opencode-ai/plugin dependency
Create basic index.ts with empty plugin
Create server.ts adapted from hook server
Implement submit_plan tool with server integration
Activity
backnotprop commentedon Dec 31, 2025
Nevermind building this
OpenCode Plannotator Plugin
Overview
Adapt Plannotator (existing Claude Code plugin at
/Users/ramos/cupcake/cupcake-rego/planning-hook) to work with OpenCode. The goal is to give OpenCode the same interactive plan review experience with visual annotation.Existing Assets (Plannotator):
apps/hook/server/index.ts(122 lines)packages/editor/App.tsx(554 lines)packages/ui/utils/parser.ts:exportDiff()What We Build: OpenCode plugin that bridges to Plannotator's server/UI.
Core Differences: Claude Code vs OpenCode
PermissionRequestonExitPlanModesubmit_planclient.tui.executeCommandCore UX Flow
Directory Structure
Implementation Plan
Step 1: Create Plugin Scaffold
Files to create:
apps/opencode-plugin/package.jsonapps/opencode-plugin/index.tsStep 2: Adapt Server for Function-Based Invocation
File to create:
apps/opencode-plugin/server.tsCurrent server reads from stdin:
New server accepts plan as parameter:
Step 3: Wire Up Browser Opening
Step 4: Complete Tool Execute Function
Step 5: Add System Prompt Injection (Optional Enhancement)
Step 6: Build Configuration
Add to
package.jsonworkspaces, create Vite config to build single-file HTML:Verification Checklist
submit_planappearsFiles to Create
apps/opencode-plugin/package.jsonapps/opencode-plugin/index.tsapps/opencode-plugin/server.tsapps/opencode-plugin/vite.config.tsFiles to Reference (Read-Only)
apps/hook/server/index.tsapps/hook/vite.config.tspackages/editor/App.tsxpackages/ui/utils/parser.tsDecisions Made
Shared build: OpenCode plugin will import the built HTML from
apps/hook/dist/index.html- single source of truth, no duplication.Detecting plan agent: Will investigate during implementation - may need to check context or use event hook.
Implementation Order
apps/opencode-plugin/directory structurepackage.jsonwith @opencode-ai/plugin dependencyindex.tswith empty pluginserver.tsadapted from hook serversubmit_plantool with server integrationbacknotprop commentedon Dec 31, 2025
merging in #3
backnotprop commentedon Dec 31, 2025
merged in #3
fix(review): address PR annotation review findings (#1, #3, #4, #5)
atreus44 commentedon Aug 14, 2026
Wow, this is where it started