Toggle a watchdog on the current root OpenCode session. After each completed assistant turn, the plugin asks a hidden judge subagent for a completion score. If the score is below the threshold, it injects a fixed synthetic continue prompt. If the score reaches or exceeds the threshold, the watchdog auto-pauses and disables itself.
This package now ships both:
- a
serverplugin half that injects a default hiddenwatchdog-judgeshell at runtime - a
tuiplugin half that provides the toggle command, right-top watchdog mode toast, and judge orchestration
- Install the plugin:
opencode plugin opencode-watchdog@latest --global-
Restart OpenCode.
-
Open a session that is still actively running, then enable watchdog with either:
ctrl+q/watchdog
If you enable it after the session is already back at the normal user-input stage, watchdog will refuse to arm. This is intentional: it only watches future turns and does not retroactively judge the already-finished last reply.
- A long-lived toast titled
Watchdog modeappears while watchdog is active for the current root session. - The toast shows five fields:
statusinputthresholdcontinueslast score
- Short result toasts use severity on purpose:
success: judge passed, watchdog auto-pausedwarning: judge did not pass and watchdog keeps going, or watchdog was manually/statically stopped
- After each later assistant completion, watchdog waits briefly, runs a hidden judge, then either:
- auto-continues when
score < threshold - auto-pauses and disables itself when
score >= threshold
- auto-continues when
Preferred install command:
opencode plugin opencode-watchdog@latest --globalIf you only want it in the current project instead of globally, omit --global:
opencode plugin opencode-watchdog@latestFor local development before publishing or while iterating:
opencode plugin "/Users/bytedance/self/opencode-watchdog"This package exposes both server and tui entries. A normal opencode plugin ... install will wire both halves automatically.
The exported TUI plugin supports these options:
commandKeybind: toggle shortcut, defaultctrl+qlanguage: default language for the built-in continue prompt and judge reason, defaultzh, allowed values:zh,enthreshold: completion score threshold for auto-pause, default70settleMs: delay after root session becomesidlebefore judge runs, default1200maxContinues: maximum automatic continues before watchdog disables itself, default8continuePrompt: fixed synthetic continue prompt overridedebug: enable extra debug entries in the watchdog log file
Parameter meanings:
languagezh: built-in continue prompt is Chinese, judge reason is requested in Chineseen: built-in continue prompt is English, judge reason is requested in English
thresholdscore < threshold: watchdog sends the synthetic continue promptscore >= threshold: watchdog auto-pauses and disables itself
settleMs- debounce window after
idle - prevents judging too early while tail events are still arriving
- debounce window after
maxContinues- hard safety cap for one watchdog run on the same root session
continuePrompt- override only if you really want a different synthetic continue text
- default
zhtext is:继续,刚才只是阶段性汇报。请继续完成当前任务,不要重复已经完成的内容。如果你认为需求已经完全完成,请明确说明理由。 - default
entext is:Continue, the last reply was only a progress update. Keep working on the current task without repeating completed work. If you believe the request is already fully finished, explain why clearly.
debug- adds more detail into the watchdog log file; it does not print to stdout/stderr
Example tui.json plugin entry:
[
"/Users/bytedance/self/opencode-watchdog",
{
"commandKeybind": "ctrl+q",
"language": "zh",
"threshold": 72,
"settleMs": 1200,
"maxContinues": 8
}
]If OpenCode is already running, restart it after installing or upgrading the plugin so the new TUI plugin code is loaded.
Hidden judge agent
By default, the package injects a fixed hidden subagent shell named watchdog-judge through its server plugin half. You do not need to add it manually for the default case, and its name is no longer a public plugin option.
Injected default shell:
{
"agent": {
"watchdog-judge": {
"mode": "subagent",
"hidden": true,
"description": "Internal watchdog judge.",
"prompt": "Follow the provided system instructions exactly and return only the requested structured result.",
"permission": {
"*": "deny",
"StructuredOutput": "allow"
}
}
}
}The real watchdog judging instructions still live inside the plugin code. This hidden agent is only a narrow execution shell.
If you already define watchdog-judge yourself, the plugin keeps your entry and does not require a second manual shell.
model is optional.
- If you configure
watchdog-judge.model, OpenCode will use that model for judge runs. - If you do not configure
watchdog-judge.model, the plugin still works and OpenCode falls back to its normal model resolution path for that judge session.
Example with an explicit model is allowed but not required:
{
"agent": {
"watchdog-judge": {
"mode": "subagent",
"hidden": true,
"description": "Internal watchdog judge.",
"model": "openai/gpt-4.1-mini",
"prompt": "Follow the provided system instructions exactly and return only the requested structured result.",
"permission": {
"*": "deny",
"StructuredOutput": "allow"
}
}
}
}That override is only needed if you want to customize the judge shell. It is not required for the package to function.
- You enable watchdog on the current root session.
- The plugin captures the latest meaningful user message as the anchor task.
- Each time the root session later becomes
idle, watchdog waitssettleMs. - It creates a temporary hidden child session named like
Watchdog judge (...). - That child returns structured JSON with
{ score, reason }. - The child session is deleted.
- Watchdog either auto-continues or auto-pauses based on the threshold.
The score means completion confidence, not answer quality:
- high score: the latest assistant reply is complete enough to stop or pause for the user
- low score: the latest assistant reply is still a phase report / incomplete execution and should continue
- if the agent is blocked and needs user clarification, permissions, environment details, credentials, or a manual decision, that also counts as a stop condition and should score high
- the
reasonfield followslanguage: Chinese whenlanguage=zh, English whenlanguage=en
- First toggle enables watchdog for the current root session.
- If the current root session is already idle and back in user-input stage, watchdog refuses to arm and shows a warning toast instead of judging the last completed reply.
- The plugin captures a task anchor from the latest meaningful user message.
- On later root-session idle events, the plugin evaluates the latest completed assistant message.
- It creates a temporary hidden child session for the judge, reads the score, then deletes that child session.
- Replies that already fall into recovery territory for the existing auto-continue plugin are skipped by watchdog, including error turns, empty-output turns, and other non-normal finishes.
- While watchdog is active on the current root session, a persistent right-top toast shows
Watchdog mode, including current status, last score, and last decision. - If
score < threshold, it sends a fixed synthetic continue prompt. - If
score >= threshold, watchdog auto-pauses and disables itself. - Toggling again manually disables watchdog immediately.
Use watchdog when you expect the agent to keep working through several turns and you want automatic continuation only while it is obviously unfinished.
Typical flow:
- Ask the agent to do a longer coding/debugging task.
- While it is still running, press
ctrl+qor run/watchdog. - Let it continue working.
- Watch the
Watchdog modetoast:- low score means watchdog will keep pushing it forward
- high score means watchdog will stop and return control to you
Do not enable it after the run is already fully back to idle and waiting for input; in that case watchdog intentionally refuses to arm.
The plugin writes runtime state transitions to:
~/.local/share/opencode/log/opencode-watchdog.log
Important entries include:
enabledskipjudge-resultcontinuedpausedjudge-failedaborted
- Root session only
- TUI only
- Uses a score-based judge, not a full multi-state workflow classifier
- Existing empty-output / error auto-continue behavior is intentionally out of scope
npm install
npm run typecheck
npm run buildDry-run package verification:
npm pack --dry-runImplementation plan lives in:
plans/2026-04-25-watchdog-plan.md