Skip to content
Development
Skill

/watch-patterns

Correct watcher construction for long-running operations. TRIGGER when: watching a long-running operation (CI, deploy, log stream), writing poll/until loops, or using the Monitor tool. SKIP: production alerts/metrics (use monitoring-observability); log formatting (use

From plugin
scaffolding
1639 skills13 agents21 commands25 hooks

Claude Code

$ npx -y skills add komluk/scaffolding --skill watch-patterns --agent claude-code

SKILL.md

watch-patterns.SKILL.md
name: watch-patterns
description: "Correct watcher construction for long-running operations. TRIGGER when: watching a long-running operation (CI, deploy, log stream), writing poll/until loops, or using the Monitor tool. SKIP: production alerts/metrics (use monitoring-observability); log formatting (use logging-standards); diagnosing the bug (use systematic-debugging)."

Watch Patterns Skill

Purpose

How to observe long-running operations correctly. Anyone can run a loop — the value is a watcher that **never lies**: it terminates, it detects failure as reliably as success, and its silence is never mistaken for progress.

Key architectural fact: a subagent cannot hold a long-lived observation. Notifications from an armed `Monitor` land in the conversation that armed it; a subagent finishes and dies. Observation is therefore always armed by the main loop — this skill is loadable anywhere for exactly that reason.

Auto-Invoke Triggers

  • Watching a CI run, deployment, file transfer, GC/prune job, or log stream
  • Writing any poll/`until` loop over a remote or local state
  • Using the `Monitor` tool or `Bash(run_in_background)` for observation

---

Decision Tree — Choose the Mechanism FIRST

The single most common failure is picking the wrong mechanism. Decide BEFORE writing any script:

| Situation | Mechanism | |-----------|-----------| | "Is it done *now*?" — answerable immediately | **One-shot check.** Single command, no loop, no monitor. | | ONE notification when a condition becomes true (deploy finished, download complete, GC done) | **`Bash(run_in_background)` + `until` loop** with a terminal condition and a bounded iteration count. NOT `Monitor`. | | REPEATING events, each occurrence matters (every error line, every restart) | **`Monitor` tool** with a filter covering ALL terminal states. | | CI run status (Gitea Actions) | **MCP polling**: `mcp__gitea__gitea-actions_run_read` polled until `status` is terminal. Structured status beats scraping logs. | | Metric/log condition (error rate, service down) | **MCP**: `mcp__grafana__grafana-query_prometheus` / `grafana-query_loki_logs`. One query returns aggregated truth; a bash loop re-derives it badly. | | You only need the outcome eventually, no urgency | **Do nothing now.** Check once when the result is actually needed. |

Anti-pattern (observed failure)

Unbounded `tail -f` / `while true` piped into `Monitor` when only ONE notification was needed → the tool stays armed until timeout, and every intermediate line risks a spurious notification. Single notification = `Bash(run_in_background)` + `until`; `Monitor` is for recurring events only.

Canonical single-notification pattern

# Bash(run_in_background): fires ONCE, always terminates
for i in $(seq 1 120); do            # bound: 120 × 30s = 1h hard ceiling
  STATUS=$(remote_status_cmd 2>&1) || STATUS="PROBE_FAILED"
  case "$STATUS" in
    *done*|*success*)  echo "RESULT: success — $STATUS"; exit 0 ;;
    *failed*|*error*)  echo "RESULT: failed — $STATUS";  exit 1 ;;
  esac
  sleep 30
done
echo "RESULT: timeout after 1h — last status: $STATUS"; exit 2

Every branch — success, failure, probe error, timeout — produces output. There is no code path that ends in silence.

---

Terminal-State Coverage (the filter must catch failure)

A filter that only matches the happy path makes a crash indistinguishable from "still running". Before arming ANY watcher, ask:

> **"If this process died right now, would my filter emit anything?"**

If the answer is no, the watcher is broken — fix it before arming.

| Filter | Verdict | |--------|---------| | `grep "success"` | BAD — crash = silence | | `grep -E "success\|complete"` | BAD — still only happy path | | `grep -E "success\|complete\|fail\|error\|fatal\|panic\|denied\|timeout"` | GOOD — alternation covers terminal states | | `until ! kill -0 "$PID" 2>/dev/null; do sleep 1; done; echo "exited rc=$(cat rcfile 2>/dev/null)"` | GOOD — process disappearance IS the event |

Rules:

  • Watch the **process/run lifecycle**, not just log content, whenever possible

(exit code, PID disappearance, API `status` field). Logs lie by omission; exit states don't.

  • For log filters, always include the failure vocabulary of the specific tool

(`FAILED`, `ERROR`, `fatal:`, `Traceback`, `panicked`, `unreachable`) — read a sample of real output first to learn it.

  • Bound every loop (max iterations) instead of `while true` whenever the

operation is expected to finish. Timeout is a terminal state too — emit it explicitly. Unbounded loops convert "it never finished" into silence.

---

Script Hygiene

| Concern | Rule | |---------|------| | Buffering | Pipelines swallow lines: use `grep --line-buffered`, `awk '{print; fflush()}'`, `stdbuf -oL` for stubborn tools. NEVER put `head -N` mid-stream — it SIGPIPEs the producer and kills the pipeline early. | | Stderr | Always `2>&1` on commands you spawn — crashes print to stderr, and a filter reading only stdout misses them. | | Transient errors | A remote probe MAY fail transiently: `OUT=$(curl -fsS "$URL" 2>&1) || OUT="PROBE_FAILED: $OUT"` — capture and classify; a blind `\|\| true` on every command converts persistent outage into silence. Count consecutive failures; N in a row = terminal state "target unreachable". | | Intervals | Remote APIs / SSH probes: **≥ 30 s**. Local files/processes: 0.5–1 s. Hammering a remote API is both rude and a great way to get rate-limited into false "failures". | | Idempotent probes | Each iteration must be self-contained. Do not cache a mount path, connection, or PID across iterations — re-resolve it (see autofs warning below). |

---

Address & Secret Acquisition (NEVER hardcode)

**IP addresses in the model's context window may be MASKED (`<PRIVATE_IP>`).** You cannot copy an IP from context into a script — you would arm a watcher pointed at a placeholder or an empty string. Observed failure: `$NAS` was empty → `/dev/tcp//22: Invalid argume

Read more
@komluk
Ships withscaffolding

Spec-driven multi-agent orchestration for Claude Code — pure markdown, zero backend, runs on the stock runtime. 13 agents, 39 skills, 21 commands, 20 hooks, per-phase model tiers, opt-in lifecycle hooks, optional cross-device semantic memory.

1639 skills13 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
16
Star history of komluk/scaffolding on GitHub, a chart by star-history.com

Other skills on scaffolding.

agent-comms

agent-comms

SendMessage recipient validation and worktreePath safety (CWE-59). TRIGGER when: validating a SendMessage `to:` recipient against…

@komluk@komlukInstall Skill
agent-memory

agent-memory

Repo-local file memory under .scaffolding/ (shared/agent/conversation tiers). TRIGGER when: reading or writing .scaffolding/…

@komluk@komlukInstall Skill
api-design

api-design

RESTful API design standards: resource naming, HTTP methods, status codes, pagination, versioning. TRIGGER when: designing new…

@komluk@komlukInstall Skill
context-engineering

context-engineering

Optimize Claude Code context-window usage for accuracy and cost. TRIGGER when: hitting context limits, structuring prompts for an…

@komluk@komlukInstall Skill
database-optimization

database-optimization

Schema design, index strategy, migration safety, and query analysis. TRIGGER when: designing tables or indexes, writing a…

@komluk@komlukInstall Skill
distill

distill

Knowledge distillation: candidate extraction, confidence scoring, tier routing. Invoked by /learn and the memory-ingest Stop…

@komluk@komlukInstall Skill

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about watch-patterns.

Which coding agents can use watch-patterns?
watch-patterns installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.