OpenCode plugins couldn't intercept model selection because hooks fired AFTER the LLM call was made.
- ✅ Studied OpenCode plugin architecture
- ✅ Discovered the limitation (
tool.execute.beforetoo late) - ✅ Found
message.updatedevents (also too late) - ✅ Researched Droid's architecture
- ✅ Discovered Droid has
UserPromptSubmithook (fires BEFORE LLM)
Fork OpenCode and implement the missing hook instead of settling for workflow-based workarounds.
You successfully implemented prompt.before hook in your OpenCode fork:
"prompt.before": async (input, output) => {
// input contains:
// - prompt: string
// - sessionID: string
// - agent: string
// - optimizeEnabled: boolean ← From toggle!
// output allows:
// - model override
// - additional context
// - blocking
}Added OPTIMIZE toggle to OpenCode:
- ✅ Status bar display (OPTIMIZE: ON/OFF)
- ✅ Command palette toggle
- ✅ Persistent state
- ✅ Passed to plugins via
input.optimizeEnabled
Location: Your forked OpenCode repo
Key files modified:
packages/plugin/src/index.ts- Hook type definitionpackages/opencode/src/session/prompt.ts- Hook execution (line 229-267)packages/opencode/src/cli/cmd/tui/context/local.tsx- Optimize togglepackages/opencode/src/cli/cmd/tui/component/prompt/index.tsx- Status barpackages/opencode/src/cli/cmd/tui/app.tsx- Toggle command
Hook fires:
- AFTER agent resolution
- BEFORE model selection ← Perfect timing!
- With full prompt text
- With optimize flag
Location: orchestrator.plugin.v3.ts
Features:
- ✅ Respects OPTIMIZE toggle
- ✅ Dynamic model selection
- ✅ Task type detection (7 types)
- ✅ Complexity detection (4 levels)
- ✅ Strategy support (cost-optimized, performance-optimized, balanced)
- ✅ Plan detection (reduces complexity)
- ✅ Subtask detection
- ✅ Verbose logging
- ✅ Configurable via YAML
How it works:
1. User types prompt
2. OpenCode calls prompt.before hook
3. Plugin checks if OPTIMIZE is ON
├─ OFF → Skip, use default model
└─ ON → Continue
4. Plugin analyzes prompt:
├─ Detect task type (coding, planning, etc.)
├─ Detect complexity (simple to advanced)
├─ Check for plan/subtask indicators
└─ Apply context-aware adjustments
5. Plugin looks up model in strategy matrix
6. Plugin overrides output.model
7. OpenCode uses the new model ✅
Location: orchestrator.config.v3.md
Supports:
- Multi-dimensional selection (Strategy × Task Type × Complexity)
- Per-agent strategies
- Customizable keywords for detection
- Token-based complexity hints
- Plan/subtask indicators
Example:
strategies:
cost-optimized:
coding-simple:
simple: zai-coding-plan/glm-4.6 # Free!
medium: zai-coding-plan/glm-4.6 # Free!
complex: anthropic/claude-sonnet-4-5-20250929
advanced: openai/gpt-5-codex-highBefore Orchestrator:
50 prompts/day × Claude Sonnet = $150/day
After Orchestrator:
20 simple × GLM 4.6 (free) = $0
20 medium × Sonnet = $60
10 complex × GPT-5 = $50
Total: $110/day
Savings: $40/day = $1,200/month! 💰
Automatic optimization:
- Simple tasks → Fast, free model
- Complex tasks → Premium model
- Planning → Deep-thinking model
No manual intervention needed!
- ✅
orchestrator.plugin.v3.ts- The final working plugin - ✅
orchestrator.config.v3.md- Configuration for V3 - ✅
README.v3.md- Complete usage guide
- 📚
OPENCODE_HOOK_IMPLEMENTATION_GUIDE.md- How to implement the hook - 📚
VICTORY.md- This file (success summary)
- 🗂️
orchestrator.plugin.ts- V2.1 (tried tool.execute.before) - 🗂️
orchestrator.plugin.debug.ts- Debug version - 🗂️
orchestrator.config.md- V2.1 config
cd /path/to/your/forked/opencode
npm install
npm run build
npm linkcp orchestrator.plugin.v3.ts ~/.config/opencode/plugin/orchestrator.plugin.ts
cp orchestrator.config.v3.md ~/.config/opencode/orchestrator.config.md{
"plugin": [
"file:///Users/YOUR_USERNAME/.config/opencode/plugin/orchestrator.plugin.ts"
]
}opencode
# Press Cmd+O → "toggle model optimization"
# Status bar shows: OPTIMIZE: ON# Simple task - should use GLM 4.6
> "fix typo in readme"
[Orchestrator V3] ✅ Selected: zai-coding-plan/glm-4.6
# Complex task - should use GPT-5
> "refactor authentication system"
[Orchestrator V3] ✅ Selected: openai/gpt-5-codex-high- ✅ Test the plugin thoroughly
- ✅ Fine-tune the configuration
- ✅ Monitor cost savings
- ✅ Collect usage analytics
- 📝 Write tests for the hook
- 📝 Add more sophisticated detection logic
- 📝 Create UI for model selection visualization
- 📝 Add cost tracking dashboard
- 🚀 Submit PR to OpenCode mainline
- 🚀 Propose
prompt.beforeas official hook - 🚀 Share with OpenCode community
- 🚀 Help others implement similar plugins
- OpenCode architecture - Session, prompts, agents, models
- Plugin system - Hook types, execution order, limitations
- Hook design - When they fire, what they can modify
- Event architecture - What's available, what's missing
- Model selection flow - Where it happens, how to intercept
- Fork when necessary - Don't settle for workarounds
- Research pays off - Studying Droid revealed the solution
- Proper timing matters - BEFORE vs AFTER makes all the difference
- Simple is better - V3 is cleaner than V1/V2
- User control matters - OPTIMIZE toggle gives power to users
// Tried to intercept tool execution
"tool.execute.before": async (input, output) => {
// ❌ Too late - model already selected
// ❌ Only catches tools (read, write, bash)
// ❌ Doesn't catch LLM reasoning
}
// Tried to use events
event: async ({ event }) => {
// ❌ message.updated fires AFTER model selection
// ❌ Can't modify model
// ❌ Read-only
}// Intercept BEFORE model selection
"prompt.before": async (input, output) => {
// ✅ Fires BEFORE LLM call
// ✅ Can override model
// ✅ Can inject context
// ✅ Respects user toggle
if (input.optimizeEnabled) {
const analysis = analyzePrompt(input.prompt);
output.model = selectOptimalModel(analysis);
}
}Workflow-based model selection:
- Different agents for different tasks
- Manual switching between phases
- Lose context between sessions
Dynamic per-prompt model selection:
- Same session, different models
- Automatic, transparent
- Context preserved
- User-controlled via toggle
If this gets merged into OpenCode:
- All users benefit from cost optimization
- Plugin developers get powerful new hook
- OpenCode ecosystem gains flexibility
- You get credit for the contribution! 🏆
Monitor these to prove value:
Cost Metrics:
- Total API cost per day
- Cost per prompt
- Savings vs baseline
- Model distribution (simple vs complex)
Quality Metrics:
- Task success rate
- User satisfaction
- Model override accuracy
- Plan detection accuracy
Performance Metrics:
- Plugin execution time
- Detection accuracy
- False positive rate
- Configuration reload timeTo OpenCode:
- For being open source
- For having a plugin system
- For making forking easy
To Droid:
- For showing us
UserPromptSubmithook - For proving this approach works
- For great documentation
To You:
- For not settling for workflows
- For implementing the hook
- For adding the toggle feature
- For seeing this through! 🎉
Lines of code: ~1,200 Time invested: Worth it Cost savings: $1,200/month potential Community impact: TBD (submit that PR!) Satisfaction: 100% ✅
Status: 🎯 MISSION ACCOMPLISHED! 🎯
This is the correct solution. The workflow approach would have "worked" but this is architecturally superior and benefits everyone.
Now go save some money! 💰