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
The tool.execute.after plugin hook can mutate output.output on the result object, and the mutation correctly propagates to Session.updatePart({ state: { output: value.output.output } }). However, the TUI renders metadata.output instead of state.output for bash tools, so the mutation is never visible to the user.
In packages/opencode/src/cli/cmd/tui/routes/session/index.tsx, the Bash component reads:
But the bash tool sets metadata.output as a separate string copy at execution time, before the hook runs:
// packages/opencode/src/tool/bash.tsreturn{title: params.description,metadata: {output: output,// ← snapshot before hookexit: proc.exitCode,},
output,// ← this gets mutated by the hook, but UI doesn't read it}
So even though the hook successfully mutates result.output, the UI never shows the change because it reads metadata.output which still has the pre-hook value.
Create a plugin that appends text to output.output in tool.execute.after:
"tool.execute.after": async(input,output)=>{if(input.tool!=="bash")returnconsttext=output.output??""if(text.includes("Operation not permitted")){output.output=text+"\n\n⚠️ Annotation from plugin"}}
Run a bash command that produces "Operation not permitted" in its output
Observe that the annotation does not appear in the TUI output panel
Expected: The annotation appears in the displayed output.
Actual: The TUI renders metadata.output (pre-hook snapshot) instead of state.output (post-hook mutated value).
I patched the installed plugin to log diagnostic data after the tool.execute.after hook runs. Here's the sanitized output from two consecutive blocked bash commands (curl google.com):
=== SANDBOX DEBUG 2026-02-14T10:09:52.286Z ===
tool: bash
mutated: true
output.output (first 200): bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted
⚠️ [opencode-sandbox] Command blocked or partially blocked by sandbox restrictions. Adjust config in .opencode/sandbox.json or OPENCODE_S
output.metadata keys: ["output","exit","description","truncated"]
output.metadata.output (first 200): bwrap: loopback: Failed RTM_NEWADDR: Operation not permitted
metaBefore === output.metadata.output: true
output.output === output.metadata.output: false
=== END ===
Key findings
Field
Value
mutated
true — the hook successfully modified output.output
output.output
Contains the appended ⚠️ [opencode-sandbox] ... annotation
output.metadata.output
Only contains the original bwrap: ... Operation not permitted — no annotation
metaBefore === output.metadata.output
true — metadata.output was never changed by the hook
output.output === output.metadata.output
false — they diverge after mutation
Debug patch used
"tool.execute.after": async(input,output)=>{if(input.tool!=="bash")return;consttext=output.output??"";constmetaBefore=output.metadata?.output;if(text.includes("Operation not permitted")||text.includes("Connection blocked by network allowlist")){output.output=text+"\n\n⚠️ ...annotation...";}// Diagnostic loggingconstfsSync=require("fs");fsSync.appendFileSync("/tmp/sandbox-debug.log",["mutated: "+(output.output!==text),"output.output === output.metadata.output: "+(output.output===output.metadata?.output),"metaBefore === output.metadata.output: "+(metaBefore===output.metadata?.output),].join("\n"));}
Conclusion
This confirms that:
The hook does mutate output.output correctly
output.metadata.output is a separate string reference assigned before the hook runs
Since JS strings are immutable, reassigning output.output creates a new reference without affecting metadata.output
The TUI reads metadata.output → the annotation is never displayed
Environment: OpenCode 1.2.1, Linux (bwrap sandbox), [email protected]
Activity
isanchez31 commentedon Feb 14, 2026
Local Validation
I patched the installed plugin to log diagnostic data after the
tool.execute.afterhook runs. Here's the sanitized output from two consecutive blocked bash commands (curl google.com):Key findings
mutatedtrue— the hook successfully modifiedoutput.outputoutput.output⚠️ [opencode-sandbox] ...annotationoutput.metadata.outputbwrap: ... Operation not permitted— no annotationmetaBefore === output.metadata.outputtrue—metadata.outputwas never changed by the hookoutput.output === output.metadata.outputfalse— they diverge after mutationDebug patch used
Conclusion
This confirms that:
output.outputcorrectlyoutput.metadata.outputis a separate string reference assigned before the hook runsoutput.outputcreates a new reference without affectingmetadata.outputmetadata.output→ the annotation is never displayedEnvironment: OpenCode 1.2.1, Linux (bwrap sandbox), [email protected]
github-actions commentedon Apr 16, 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.