@pi-unipi/watchdog

Jev watchdog for long-running tool calls and background tasks — judges stuck work via TypeSafe System One and kills or warns

Packages

Package details

extension

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 bash calls 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
  1. Type /unipi:settings.
  2. Open the Watchdog group.
  3. Adjust the defaults if needed; bash watching is already enabled.
  4. 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

  1. A timer runs every 15 seconds or less. It does not call jev until an item is due.
  2. 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.
  3. jev answers two questions. status is one of progressing, waiting, stuck or looping. persistent scores if the item is a service that runs normally.
  4. Watchdog acts when all of these are true:
    • status is stuck or looping.
    • The confidence is at or above confidence.
    • The item is not a normal service. A looping item is never a normal service.
    • agreeChecks checks 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.

See also