Skip to content

Add watch plugin: /watch real-time Chrome monitor#2

Open
ShawnPana wants to merge 2 commits into
mainfrom
add-watch-plugin
Open

Add watch plugin: /watch real-time Chrome monitor#2
ShawnPana wants to merge 2 commits into
mainfrom
add-watch-plugin

Conversation

@ShawnPana

@ShawnPana ShawnPana commented Jun 16, 2026

Copy link
Copy Markdown
Collaborator

What

Adds a watch plugin, colocated as a subdirectory (watch/) with source: ./watch — same pattern as qa.

/watch runs a background monitor over your Chrome and, when you ask, tells you exactly what happened. It captures two streams:

  • Structured timeline (the authoritative record): network requests/responses, console logs + exceptions, and your actions — clicks, typing (field + length, never raw text), key presses, scrolls, navigations/searches — tagged per tab.
  • Dense frame recording (~2.5 fps): consulted on demand for visual detail.

It follows the active tab across all tabs (including tabs already open before you started) and is not a daemon you maintain — the agent spawns the monitor and stops it within the session.

Layout

watch/
├── .claude-plugin/plugin.json
└── skills/watch/
    ├── SKILL.md      # /watch entry: spawn monitor in background → on a question, stop + answer
    └── monitor.py    # background CDP monitor (frames + timeline) it spawns

How it works

On invoke, the skill spawns monitor.py via browser-harness in the background. The monitor uses CDP auto-attach to follow every tab, captures actions via a nav-proof Runtime.addBinding channel (with a JS-buffer fallback for pre-existing pages), pulls network/console from the event stream, and screenshots whichever tab is in front. On your next question it stops cleanly (a STOP sentinel), reads the full timeline first, then loads only the relevant frame slice for visuals.

Dependency on browser-harness

watch runs entirely through the browser-harness plugin + CLI. As with qa, there's no manifest-level "requires" field, so the dependency is documented in the description/plugin.json and the SKILL.md verifies browser-harness is on PATH before running.

Privacy & scope

  • Input is captured as field identity + character count only — never raw keystrokes; password fields redacted.
  • Captures only Chrome (the page's own CDP stream) — no OS screen-recording permission. (Address-bar/omnibox typing is therefore not captured, only the resulting URL.)

Install (after merge)

claude plugin marketplace add browser-use/plugins
claude plugin install browser-harness@browser-use
claude plugin install watch@browser-use
/watch

Validation

  • marketplace.json (now 3 plugins) and plugin.json parse as valid JSON; monitor.py compiles.
  • Exercised end-to-end across multiple live sessions: follows tab switches, captures pre-existing tabs, logs clicks/typing/scrolls/searches, and reconstructs real multi-tab sessions (incl. page-load timing from the network stream).

🤖 Generated with Claude Code


Summary by cubic

Adds the /watch plugin to monitor Chrome in real time and answer “what happened” with a structured timeline plus lightweight frame slices. Registers watch in the marketplace and README, with safeguards to keep disk usage bounded.

  • New Features

    • New watch/ plugin with plugin.json, skills/watch/SKILL.md, and skills/watch/monitor.py.
    • Structured timeline (network, console logs/errors, user actions) per tab, plus dense frames (~2.5 fps) read in small slices around relevant timestamps.
    • Follows the active tab across all tabs; starts/stops per session via browser-harness (no OS screen recording).
  • Bug Fixes

    • Auto-cleanup: purge old /tmp/watch-* dirs (keep newest 3) and switch to time-based frame trimming to prevent runaway disk usage.
    • net.fail now includes the failing request’s URL/domain by tracking requestId -> url.

Written for commit f0268c6. Summary will update on new commits.

Review in cubic

Colocated plugin (watch/) that monitors the user's Chrome live — network,
console logs, and user actions (clicks/typing/navigations) plus a dense
screen recording — and answers what happened on demand. Follows the active
tab across all tabs. Depends on the browser-harness plugin + CLI, checked
in the skill.

- watch/.claude-plugin/plugin.json — plugin manifest
- watch/skills/watch/SKILL.md — /watch entry; spawn monitor, stop+answer flow
- watch/skills/watch/monitor.py — background CDP monitor (frames + timeline)
- marketplace.json — register "watch" with source: ./watch
- README — add watch row + install line

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="watch/skills/watch/monitor.py">

<violation number="1" location="watch/skills/watch/monitor.py:76">
P2: Monitor can drop final browser events on shutdown because STOP is checked before a final event drain. This can miss the latest actions/network records right when answering a question.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

return sid

rec("watch.started", {"dir": WATCH_DIR})
while not os.path.exists(STOP):

@cubic-dev-ai cubic-dev-ai Bot Jun 16, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Monitor can drop final browser events on shutdown because STOP is checked before a final event drain. This can miss the latest actions/network records right when answering a question.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At watch/skills/watch/monitor.py, line 76:

<comment>Monitor can drop final browser events on shutdown because STOP is checked before a final event drain. This can miss the latest actions/network records right when answering a question.</comment>

<file context>
@@ -0,0 +1,136 @@
+    return sid
+
+rec("watch.started", {"dir": WATCH_DIR})
+while not os.path.exists(STOP):
+    now = time.time()
+    tgts = page_targets()
</file context>
Fix with cubic

- monitor.py: purge old /tmp/watch-* dirs on start (keep newest 3) and
  switch the in-session frame trim to a time-based sweep so it isn't
  skipped when loop iterations are slow (many tabs) — fixes unbounded
  frame growth (a single session had ballooned to 2.4GB).
- monitor.py: capture requestId->url so net.fail names the failing
  domain (e.g. ERR_NAME_NOT_RESOLVED -> https://dead-host/...).
- SKILL.md: document the auto-cleanup + how to drop the current session.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="watch/skills/watch/monitor.py">

<violation number="1" location="watch/skills/watch/monitor.py:32">
P2: Session purge can delete active monitor directories from concurrent /watch runs. Restrict deletion to finished sessions (for example dirs already containing STOP) before rmtree.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

except OSError: pass
for _, p in sorted(dirs, reverse=True)[KEEP_DIRS:]:
if p != WATCH_DIR:
shutil.rmtree(p, ignore_errors=True)

@cubic-dev-ai cubic-dev-ai Bot Jun 17, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Session purge can delete active monitor directories from concurrent /watch runs. Restrict deletion to finished sessions (for example dirs already containing STOP) before rmtree.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At watch/skills/watch/monitor.py, line 32:

<comment>Session purge can delete active monitor directories from concurrent /watch runs. Restrict deletion to finished sessions (for example dirs already containing STOP) before rmtree.</comment>

<file context>
@@ -13,7 +13,25 @@
+            except OSError: pass
+    for _, p in sorted(dirs, reverse=True)[KEEP_DIRS:]:
+        if p != WATCH_DIR:
+            shutil.rmtree(p, ignore_errors=True)
+
+purge_old_sessions()
</file context>
Suggested change
shutil.rmtree(p, ignore_errors=True)
if os.path.exists(os.path.join(p, "STOP")):
shutil.rmtree(p, ignore_errors=True)
Fix with cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant