{"slug":"ops-monitor","title":"ops-monitor","summary":"Unified APM and monitoring surface. Polls Datadog, New Relic, and OpenTelemetry backends for active alerts, error traces, and entity health. Use --watch for live polling every 60 seconds. Use --setup to configure monitoring credentials.","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-14T20:43:21.187572Z","repo":{"url":"https://github.com/davepoon/buildwithclaude","stars":3609,"forks":577,"license":"MIT","updatedAt":"2026-10-09T07:12:21Z"},"bodyHtml":"<hr>\n<p>name: ops-monitor\ndescription: Unified APM and monitoring surface. Polls Datadog, New Relic, and OpenTelemetry backends for active alerts, error traces, and entity health. Use --watch for live polling every 60 seconds. Use --setup to configure monitoring credentials.\nargument-hint: \"[--watch] [--setup] [--backend datadog|newrelic|otel]\"\nallowed-tools:</p>\n<ul>\n<li>Bash</li>\n<li>Read</li>\n<li>Agent</li>\n<li>AskUserQuestion</li>\n<li>TeamCreate</li>\n<li>SendMessage\neffort: low\nmaxTurns: 20</li>\n</ul>\n<hr>\n<h2>Runtime Context</h2>\n<pre><code>PREFS=\"${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json\"\nDD_API_KEY=$(jq -r '.datadog_api_key // empty' \"$PREFS\" 2&gt;/dev/null)\nNR_API_KEY=$(jq -r '.newrelic_api_key // empty' \"$PREFS\" 2&gt;/dev/null)\nOTEL_ENDPOINT=$(jq -r '.otel_endpoint // empty' \"$PREFS\" 2&gt;/dev/null)\n</code></pre>\n<p>Determine <code>$ARGUMENTS</code> mode:</p>\n<ul>\n<li>Contains <code>--setup</code> → run <strong>Setup flow</strong></li>\n<li>Contains <code>--watch</code> → run <strong>Watch mode</strong></li>\n<li>Otherwise → run <strong>Default health check</strong></li>\n</ul>\n<h1>OPS ► MONITOR</h1>\n<h2>Setup flow (<code>--setup</code>)</h2>\n<p>Ask which backends to configure:</p>\n<pre><code>Which monitoring backends would you like to configure?\n[Datadog]  [New Relic]  [OpenTelemetry]  [All three]\n</code></pre>\n<p>For each selected backend, collect credentials via <code>AskUserQuestion</code> free-text input (one at a time, ≤4 options per call):</p>\n<p><strong>Datadog:</strong></p>\n<ol>\n<li><code>datadog_api_key</code> — API Key from app.datadoghq.com/organization-settings/api-keys</li>\n<li><code>datadog_app_key</code> — Application Key from app.datadoghq.com/organization-settings/application-keys</li>\n</ol>\n<p><strong>New Relic:</strong></p>\n<ol>\n<li><code>newrelic_api_key</code> — User API Key from one.newrelic.com/api-keys</li>\n<li><code>newrelic_account_id</code> — Numeric Account ID from New Relic admin portal</li>\n</ol>\n<p><strong>OpenTelemetry:</strong></p>\n<ol>\n<li><code>otel_endpoint</code> — Base URL of your OTEL-compatible backend (e.g., <a href=\"https://otlp.grafana.net\">https://otlp.grafana.net</a>)</li>\n</ol>\n<p>Write each credential to preferences.json using atomic tmpfile swap:</p>\n<pre><code>tmp=$(mktemp)\njq --arg k \"$KEY\" --arg v \"$VALUE\" '.[$k] = $v' \"$PREFS\" &gt; \"$tmp\" &amp;&amp; mv \"$tmp\" \"$PREFS\"\n</code></pre>\n<p>Run smoke test after saving:</p>\n<ul>\n<li><strong>Datadog</strong>: <code>curl -sf -H \"DD-API-KEY: $DD_API_KEY\" -H \"DD-APPLICATION-KEY: $DD_APP_KEY\" \"https://api.datadoghq.com/api/v1/validate\"</code> → expect <code>{\"valid\": true}</code></li>\n<li><strong>New Relic</strong>: <code>curl -sf -H \"Api-Key: $NR_API_KEY\" \"https://api.newrelic.com/graphql\" -d '{\"query\":\"{ actor { user { name } } }\"}'</code> → expect <code>data.actor.user</code></li>\n<li><strong>OTEL</strong>: <code>curl -sf \"$OTEL_ENDPOINT/healthz\"</code> → expect HTTP 200</li>\n</ul>\n<p>Report ✅ or ❌ with status for each backend.</p>\n<h2>Agent Teams support</h2>\n<p>If <code>CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1</code> is set, use <strong>Agent Teams</strong> when querying multiple backends simultaneously. This enables:</p>\n<ul>\n<li>Backend probes run in parallel with shared context (e.g., Datadog agent detects latency spike → OTEL agent can correlate with traces)</li>\n<li>You can steer: \"focus on Datadog alerts first, then cross-reference with New Relic\"</li>\n<li>Real-time progress: agents report per-backend as results arrive</li>\n</ul>\n<p><strong>Team setup</strong> (only when flag is enabled, multiple backends configured):</p>\n<pre><code>TeamCreate(\"monitor-probes\")\nAgent(team_name=\"monitor-probes\", name=\"datadog-probe\", subagent_type=\"ops:monitor-agent\", ...)\nAgent(team_name=\"monitor-probes\", name=\"newrelic-probe\", subagent_type=\"ops:monitor-agent\", ...)\nAgent(team_name=\"monitor-probes\", name=\"otel-probe\", subagent_type=\"ops:monitor-agent\", ...)\n</code></pre>\n<p>If the flag is NOT set or only one backend is configured, use a single <code>monitor-agent</code> subagent.</p>\n<h2>Default health check (no flags)</h2>\n<p>Spawn <code>monitor-agent</code> via the Agent tool. Display the result as a formatted dashboard:</p>\n<pre><code>━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n OPS ► MONITOR                       [&lt;timestamp&gt;]\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n DATADOG      ✅ healthy (0 alerts)\n NEW RELIC    \uD83D\uDD34 2 critical entities\n OTEL         ✅ healthy\n──────────────────────────────────────────────────────\n Total alerts: 2   Severity: CRITICAL\n</code></pre>\n<p>Status icons:</p>\n<ul>\n<li><code>✅</code> — healthy (0 alerts / configured and reachable)</li>\n<li><code>⚠️</code> — warning (warn-level alerts present)</li>\n<li><code>\uD83D\uDD34</code> — critical (critical alerts or unreachable)</li>\n<li><code>⬜</code> — not configured</li>\n</ul>\n<p>For each alert or critical entity, display: service name, alert name, and link to the relevant dashboard.</p>\n<p>If no backends are configured, show a setup prompt:</p>\n<pre><code>No monitoring backends configured. Run /ops:monitor --setup to add Datadog, New Relic, or OTEL.\n</code></pre>\n<h2>Watch mode (<code>--watch</code>)</h2>\n<p>Poll every 60 seconds. On each tick:</p>\n<pre><code>while true; do\n  RESULT=$(# spawn monitor-agent and capture JSON output)\n  # Diff against previous tick\n  # Print: timestamp, changed items only\n  # \uD83C\uDD95 new alert: &lt;name&gt;\n  # ✅ resolved: &lt;name&gt;\n  sleep 60\ndone\n</code></pre>\n<p>Exit on Ctrl-C.</p>\n<h2><code>--backend</code> filter</h2>\n<p>If <code>--backend datadog|newrelic|otel</code> is specified, query and display only that backend.</p>\n<h2>CLI/API Reference</h2>\n<table>\n<thead>\n<tr>\n<th>Backend</th>\n<th>Auth header</th>\n<th>Base URL</th>\n<th>Health endpoint</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Datadog</td>\n<td><code>DD-API-KEY: $key</code> + <code>DD-APPLICATION-KEY: $app_key</code></td>\n<td><a href=\"https://api.datadoghq.com\">https://api.datadoghq.com</a></td>\n<td>/api/v1/validate</td>\n</tr>\n<tr>\n<td>New Relic</td>\n<td><code>Api-Key: $key</code></td>\n<td><a href=\"https://api.newrelic.com/graphql\">https://api.newrelic.com/graphql</a></td>\n<td>POST GraphQL query</td>\n</tr>\n<tr>\n<td>OTEL</td>\n<td>varies by backend</td>\n<td><code>$OTEL_ENDPOINT</code></td>\n<td>/healthz</td>\n</tr>\n</tbody>\n</table>\n<pre><code># Datadog — active alerts\ncurl -sf \\\n  -H \"DD-API-KEY: ${DD_API_KEY}\" \\\n  -H \"DD-APPLICATION-KEY: ${DD_APP_KEY}\" \\\n  \"https://api.datadoghq.com/api/v1/monitor?monitor_tags=*&amp;with_downtimes=false\" \\\n  | jq '[.[] | select(.overall_state == \"Alert\" or .overall_state == \"Warn\")]'\n\n# New Relic — critical entities (GraphQL)\ncurl -sf \\\n  -H \"Api-Key: ${NR_API_KEY}\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"query\":\"{ actor { entitySearch(queryBuilder: {alertSeverity: CRITICAL}) { results { entities { name alertSeverity entityType } } } } }\"}' \\\n  \"https://api.newrelic.com/graphql\"\n\n# OTEL — health check\ncurl -sf \"${OTEL_ENDPOINT}/healthz\"\n</code></pre>\n","files":[{"path":"SKILL.md","sizeBytes":6389,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-14T20:43:43.554804Z","sha256":"0CCB687112853887FF7C630AB0C4C46C43E3856814F01C747B7D0805610ECF78","sizeBytes":2694},"review":null,"source":{"repositoryUrl":"https://github.com/davepoon/buildwithclaude","path":"plugins/claude-ops/skills/ops-monitor","license":"MIT","commit":"616deb5c66db0b06a6afeb7ae675e70a1b6e3b34","subtreeSha":"53454E6143B8D4E22D2E17F185840273478BAB69D7B7EE06C3E1BACFEB361010","lastSyncedAt":"2026-10-10T01:48:58.082839Z"},"reviewedAt":"2026-09-14T20:44:35.080325Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/davepoon/buildwithclaude/tree/main/plugins/claude-ops/skills/ops-monitor"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install davepoon-buildwithclaude@llmmart"},{"target":"git","command":"git clone https://github.com/davepoon/buildwithclaude.git"}]}