ops-go — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ops-go (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Before executing, load available context:
${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.jsonowner — use in the greeting header ("Good morning, [owner]")timezone — display all timestamps in this timezonedefault_channels — which channels to include in unread summary${CLAUDE_PLUGIN_DATA_DIR}/daemon-health.jsonaction_needed is not null → surface it before the briefingwhatsapp-bridge status before including WhatsApp unread countslsof -i :8080 | grep LISTENlsof -i :8080 | grep LISTEN).Bridge health — check before any WhatsApp operation:
lsof -i :8080 | grep LISTEN → proceedlaunchctl kickstart -k gui/$(id -u)/com.${USER}.whatsapp-bridge, wait 5s| Tool | Params | Output |
|---|---|---|
mcp__whatsapp__list_chats | {sort_by: "last_active"} | Array of chats with jid, name, last_message_time |
mcp__whatsapp__list_messages | {chat_jid, limit, query} | Message array with is_from_me, content, timestamp |
| Command | Usage | Output |
|---|---|---|
gog calendar events --all --today --json --sort start | Today's events across all calendars (sorted by start time) | Calendar events with CalendarID field for attribution |
gog gmail search -j --results-only --no-input --max 30 "in:inbox" | Search inbox | JSON array of threads |
If CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 is set, use Agent Teams when gathering briefing data in parallel. This enables:
Team setup (only when flag is enabled):
TeamCreate("go-team")
Agent(team_name="go-team", name="infra-scanner", prompt="Check ECS health, Vercel status, and CI failures across all clusters")
Agent(team_name="go-team", name="inbox-scanner", prompt="Scan unread messages across WhatsApp, Email, Slack, Telegram, Notion")
Agent(team_name="go-team", name="pr-scanner", prompt="Find open PRs needing action — reviews, CI fixes, merge-ready")
Agent(team_name="go-team", name="sprint-scanner", prompt="Check Linear sprint progress and GSD phase state across projects")If the flag is NOT set, use standard fire-and-forget subagents.
All data below was collected by shell scripts in <10 seconds.
Pulls current burn, anomalies, and revenue from the dashboard. Fails open to {} if FINOPS_DASHBOARD_URL / FINOPS_OPS_API_TOKEN are unset — in that case the briefing falls back to the per-source data below.
${CLAUDE_PLUGIN_ROOT}/scripts/finops-bridge.sh snapshot 2>/dev/null || echo "{}"Interpreting the snapshot — two different empty states, do NOT conflate:
FINOPS_DASHBOARD_URL / FINOPS_OPS_API_TOKENgenuinely unset (or the dashboard is down). Report "FinOps creds unset" and fall back to per-source AWS Cost Explorer / Infrastructure below.
generated_at) but services_tracked: 0 andall-zero current_month_spend/revenue_snapshot → dashboard reachable + authenticated, but its ingest pipeline is unpopulated**. This is NOT a creds problem — do NOT report "token unset". Say "FinOps dashboard reachable but ingest empty" and fall back to per-source data for burn/revenue.
When the snapshot has non-zero services_tracked, prefer it for the burn/runway/anomaly lines. The per-source Infrastructure and AWS Cost Explorer sections below are the fallback for both empty states above.
${CLAUDE_PLUGIN_ROOT}/bin/ops-infra 2>/dev/null || echo '{"clusters":[],"error":"infra check failed"}'${CLAUDE_PLUGIN_ROOT}/bin/ops-git 2>/dev/null || echo '[]'${CLAUDE_PLUGIN_ROOT}/bin/ops-prs 2>/dev/null || echo '[]'${CLAUDE_PLUGIN_ROOT}/bin/ops-ci 2>/dev/null || echo '[]'${CLAUDE_PLUGIN_ROOT}/bin/ops-unread 2>/dev/null || echo '{}'for d in $(jq -r '.projects[] | select(.gsd == true) | .paths[]' "${CLAUDE_PLUGIN_ROOT}/scripts/registry.json" 2>/dev/null); do
expanded="${d/#\~/$HOME}"
if [ -f "$expanded/.planning/STATE.md" ]; then
alias=$(basename "$expanded")
phase=$(grep -m1 'current_phase' "$expanded/.planning/STATE.md" 2>/dev/null | head -1 || echo "unknown")
progress=$(grep -m1 'progress' "$expanded/.planning/STATE.md" 2>/dev/null | head -1 || echo "unknown")
echo "$alias: $phase | $progress"
fi
donesource "${CLAUDE_PLUGIN_ROOT}/scripts/lib/competitor/context.sh" 2>/dev/null \
&& competitor_context --window-days 7 2>/dev/null \
|| echo '{"configured":false}'${CLAUDE_PLUGIN_ROOT}/bin/ops-external 2>/dev/null || echo '[]'${CLAUDE_PLUGIN_ROOT}/bin/ops-marketing-dash 2>/dev/null || echo '{}'home_automation is configured)if jq -e '.home_automation' "${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json" >/dev/null 2>&1; then
${CLAUDE_PLUGIN_ROOT}/bin/ops-home snapshot 2>/dev/null || echo '{"configured":true,"error":"home probe failed"}'
else
echo '{"configured":false}'
figog calendar events --all --today --json --sort start 2>/dev/null | head -60 || echo "calendar unavailable"Events include a CalendarID field (e.g. [email protected], [email protected]). When rendering the briefing, attribute each event with a short calendar label in parentheses — derive it from the CalendarID domain or summary (e.g. work account → (work), personal Gmail → (personal)). Show total count + top 3 events sorted by start time with format: HH:MM Title (calendar).
Fallback: if gog is unavailable and GOOGLE_CALENDAR_IDS env var is set (comma-separated calendar IDs), fetch each ID individually:
for id in $(echo "$GOOGLE_CALENDAR_IDS" | tr ',' '\n'); do
gog calendar events "$id" --today --json 2>/dev/null
doneAnalyze ALL the pre-gathered data above and present it as a morning briefing. Follow the ops-briefing output style.
Format:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
OPS ► MORNING BRIEFING — [DATE]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
FIRES (fix now)
[table of production issues, CI failures, broken deploys]
PRs NEEDING ACTION
[table: repo, PR#, title, status, action needed]
PORTFOLIO DASHBOARD
[table: project, phase, branch, uncommitted, CI, next action]
EXTERNAL PROJECTS
[table: alias, source, status, details — from ops-external data]
MARKETING
Health: [N]/100 ([Healthy/Warning/Critical]) | Blended ROAS: [X]x | Top channel: [channel]
Meta: $[X] spent (7d) [X]x ROAS | Google: $[X] spent (7d) [X]x ROAS | Email: [N] subs
[If health < 70: "⚠ Run /ops:marketing optimize for recommendations"]
[If no marketing configured: "(marketing not configured — /ops:marketing setup)"]
COMPETITOR <brand>: N alerts · M med deltas · last run YYYY-MM-DD
<top high-severity event snippet, 1 line, truncated 140 chars>
[If competitor data returns {configured:false}, omit this section entirely — no "(not configured)" noise]
[Mobile mode (Rule 7): compress to one line: "comp: N alerts (top: brief snippet)"]
HOME
Power: [X]W now · [Y]kWh today | Alarms: [N] active ([severity]) | Presence: [home/empty since HH:MM] | Last flow: [name @ HH:MM]
[If home data returns {configured:false}, omit this section entirely — no clutter]
[If critical alarm active (smoke/water/security): prepend `⚠ CRITICAL` and route to FIRES at top]
UNREAD
[WhatsApp: N, Email: N, Slack: N workspace(s) configured (no scan), Notion: N items, Calendar: N events today]
TODAY'S PRIORITIES (ranked by revenue impact + urgency)
1. [action] — [project] — [why]
2. ...
3. ...
──────────────────────────────────────────────────────Marketing section data source: Read from ops-marketing-dash pre-gathered output (see Pre-gathered data section). If marketing data is present in the dash output, compute the health score inline (see ops-marketing SKILL.md health score formula). If ops-marketing-dash is not configured or returns empty marketing data, show (marketing not configured — /ops:marketing setup).
Priority ranking: fires > degraded infra > CI failures > competitor alerts (high-severity, last 24h) > unread comms > ready-to-merge PRs > revenue-generating GSD work > stale projects.
If $ARGUMENTS contains a project alias, focus the briefing on that project only.
After the briefing, use batched AskUserQuestion calls (max 4 options each) for the "What's next?" prompt. Show the top 3 priority actions + [More...] in the first call, then remaining actions + [/ops-yolo — let me run your business today] in the second call. Route to the appropriate ops skill or project.
For Slack counts: read the channels.slack object from the pre-gathered data and surface workspace presence ONLY. Do NOT auto-scan Slack workspaces during briefings — Slack scans are expensive, noisy, and frequently produce stale/unread counts that don't match the user's actual triage state. The user explicitly opted out of auto-scan on briefing surfaces.
workspaces array is present: render Slack: N workspace(s) configured (<name1>, <name2>) — run /ops:ops-inbox to scan.available: false for all workspaces: show Slack: not configured and skip.mcp__claude_ai_Slack__* or curl Slack APIs from this skill. Defer all Slack scans to /ops:ops-inbox where the user explicitly opts in.For Notion counts: if NOTION_MCP_ENABLED=true and pre-gathered data shows Notion as available, use mcp__claude_ai_Notion__notion-search with query: "" sorted by last_edited_time descending to surface recently active pages. Then call mcp__claude_ai_Notion__notion-get-comments on the top results to find comments needing response. Note: Notion search does not support date range filters — sort by recency and limit to the first 10-20 results instead.
After presenting the briefing, create a TaskCreate for each recommended priority action. As the user works through them (or delegates via skill routing), update with TaskUpdate. This gives continuity across the session.
After the first briefing, offer to schedule recurring briefings via AskUserQuestion:
[Schedule daily at 9am] [Schedule weekday mornings] [No schedule]Use CronCreate to set up the schedule. Show existing schedules with CronList.
When gog calendar fails, use WebFetch with the Google Calendar API as fallback:
WebFetch(url: "https://www.googleapis.com/calendar/v3/calendars/primary/events?timeMin=<today>T00:00:00Z&timeMax=<today>T23:59:59Z")CLAIM_KEY: daily-brief:<YYYY-MM-DD> (e.g. daily-brief:2026-05-28)
Before generating the briefing, check whether one was already produced today:
BRIEF_DATE=$(date +%Y-%m-%d)
CLAIM_KEY="daily-brief:${BRIEF_DATE}"
ledger query --claim-key "$CLAIM_KEY" --since=-PT24HIf the query returns a done or in_progress entry, surface it to the user ("Briefing already ran today at HH:MM — rerun?") instead of re-fetching all sources.
# Claim at briefing start
ledger write \
--claim-key "$CLAIM_KEY" \
--kind "file" \
--status "in_progress" \
--title "Morning briefing ${BRIEF_DATE}" \
--ttl-sec 86400
# Resolve after briefing is presented to the user
ledger write \
--claim-key "$CLAIM_KEY" \
--kind "file" \
--status "done" \
--title "Morning briefing ${BRIEF_DATE}" \
--context "N fires, N PRs, N unread"~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.