@pi-unipi/watchdog
Jev watchdog for long-running tool calls and background tasks — judges stuck work via TypeSafe System One and kills or warns
Package details
Install @pi-unipi/watchdog from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@pi-unipi/watchdog- Package
@pi-unipi/watchdog- Version
3.0.1- Published
- Nov 2, 2026
- Downloads
- 4,707/mo · 466/wk
- Author
- neuron-mr-white
- License
- MIT
- Types
- extension
- Size
- 57 KB
- Dependencies
- 2 dependencies · 2 peers
Pi manifest JSON
{
"skills": [],
"themes": [],
"prompts": [],
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
Watchdog
Watchdog is on by default for bash calls; a stuck-looking call is handed to the background, never killed by default.
@pi-unipi/watchdog · part of UniPi
What it does
- Watches running
bashcalls by default; background tasks and other tools are opt-in. - Asks jev, the UniPi Decision Model, if each item is progressing, waiting, stuck or looping.
- Acts only after 2 checks in a row agree, using a stop score of 0.5 (bash) or status confidence of 0.5 (other items).
- Protects dev servers, file watchers and daemons that run normally.
- Gives the agent the background task ID, captured output and reason, so it can use
bg_logs,bg_kill, or carry on. - Never automatically judges or kills a task it moved to the background.
- Is on by default for bash only. With no watched calls, the heartbeat makes no jev requests.
Quick start
Watchdog ships in @pi-unipi/unipi. To install it alone:
pi install npm:@pi-unipi/watchdog
- Type
/unipi:settings. - Open the Watchdog group.
- Adjust the defaults if needed; bash watching is already enabled.
- Start a new session. Watchdog starts its timer at session start.
/unipi:bg-detach [reason] manually moves the most recently started foreground bash call to the background. It works independently of the automatic watchdog setting. Watchdog has no agent tools.
What it watches
| Item | Setting | Action |
|---|---|---|
bash tool calls |
watchBash |
Returns the call early and adopts its process as a background task by default. |
| Background tasks | watchBgTasks |
Stops the task through the background task registry. |
| Other tools (web, image, MCP, subagents) | otherTools |
Warns, or aborts the turn. |
Watchdog never watches read, write, edit, grep, find, ls, ask_user, read_subagent, bg_kill or bg_tasks. It also skips a background task that has no completion trigger, because that task is a server.
Settings
Open /unipi:settings → Watchdog. The namespace is watchdog.
| Key | Default | What it does |
|---|---|---|
enabled |
true |
Turns the watchdog on. |
intervalMin |
3 |
Minutes between two checks of one item. |
firstCheckMin |
2 |
Minimum age of an item, in minutes, before its first check. |
confidence |
0.5 |
Stop score for bash; status confidence for background tasks and other tools. Range 0 to 1. |
agreeChecks |
2 |
Number of checks in a row that must agree. |
action |
background |
background returns bash early without killing; kill stops it; warn leaves it running and queues a warning. |
watchBash |
true |
Watches bash calls. |
watchBgTasks |
false |
Watches background tasks. |
otherTools |
off |
off, warn or abort-turn for tools that Watchdog cannot stop. |
The group also has a Decision model section. Set decisionModel.source to inherit or custom.
action applies to bash calls only. Ordinary stuck background tasks retain the existing stop behavior even when action is warn; watchdog-adopted tasks are excluded entirely.
How a bash call is judged
Bash calls use Linux process activity plus jev's stop question. A call triggers when:
- Two checks are idle with no CPU, disk or output activity, and no sleeping process.
- The stop score meets the threshold for the configured consecutive checks.
- Jev expects the command to finish within seconds, but it has reached its first watchdog check.
An explicit timeout, chained sleep, or bounded seq/sleep loop vetoes every trigger until its declared time bound expires. Missing process samples never count as idle. Background tasks and other tools retain the existing status-based decision path.
How it works
- A timer runs every 15 seconds or less. It does not call jev until an item is due.
- For each due item, Watchdog sends jev the command and its run time. It also sends the time since new output, and the last 3,000 characters of output.
- jev answers two questions.
statusis one ofprogressing,waiting,stuckorlooping.persistentscores if the item is a service that runs normally. - Watchdog acts when all of these are true:
statusisstuckorlooping.- The confidence is at or above
confidence. - The item is not a normal service. A
loopingitem is never a normal service. agreeCheckschecks in a row agree.
Utility wraps pi's local bash operations in every render style. When detaching, the background-task registry takes ownership of the same child, output stream and original start time. The tool returns normally; completion later sends the normal background notification and wakes the agent. Esc after detachment does not stop the adopted command. Background-task shutdown cleanup and bg_kill still apply.
If adoption is unavailable (for example, background-tasks is disabled), automatic background falls back to the existing kill path: it stops the process group only when exactly one child matches the command. With zero or many matches, or on Windows, it queues a warning. Explicit kill uses that same path.
The tool result of a stopped call starts with a line like this:
⚠ Killed by unipi watchdog after 410s: jev judged it judged stuck; stuck (confidence 0.92) on 2 consecutive checks — no new output for 300s. Do not blindly re-run; investigate or change approach.
The original output follows. The result has isError: true. Warnings go to the agent at the start of the next turn. While Watchdog watches items, the status bar shows watchdog: N.
Debug log
For action-path testing, UNIPI_WATCHDOG_FORCE_ACT=1 forces an act decision at a due check; normal decision prompting and thresholds are otherwise unchanged. Do not enable this in normal sessions.
Set UNIPI_DEBUG_WATCHDOG=1 to write a log to ~/.unipi/logs/watchdog.log. Each check writes one line with the status, the confidence and the streak.