Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
davepoon avatar

Ops Daemon

  • 58 installs
  • 3.2k repo stars
  • Updated August 2, 2026
  • davepoon/buildwithclaude

Check the claude-ops background launchd daemon end-to-end and auto-fix stale plist paths, dead processes, and corrupt health files.

About

Diagnoses and auto-repairs the claude-ops macOS launchd background daemon that keeps briefing, memory, and message-listener services alive. A developer uses it when the ops daemon breaks after a plugin upgrade or process death.

  • Detects stale plist paths, dead processes, corrupt health files, and bash mismatches
  • Manager script supports status/install/upgrade/restart/uninstall with --dry-run

Ops Daemon by the numbers

  • 58 all-time installs (skills.sh)
  • Ranked #665 of 1,438 DevOps & CI/CD skills by installs in the Skillselion catalog
  • Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/davepoon/buildwithclaude --skill ops-daemon

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs58
repo stars3.2k
Last updatedAugust 2, 2026
Repositorydavepoon/buildwithclaude

What it does

Check the claude-ops background launchd daemon end-to-end and auto-fix stale plist paths, dead processes, and corrupt health files.

Files

SKILL.mdMarkdownGitHub ↗

Runtime Context

Before diagnosing, load:

1. Plugin root: echo "${CLAUDE_PLUGIN_ROOT:-$(ls -d "$HOME/.claude/plugins/cache/ops-marketplace/ops"/*/ 2>/dev/null | sort -V | tail -1)}" — newest installed version 2. Daemon health: cat ${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/daemon-health.json — primary diagnostic input 3. Services config: cat ${CLAUDE_PLUGIN_DATA_DIR}/daemon-services.json — per-service command + cron definitions 4. OS: uname -s — daemon install is macOS-only (launchd). Linux/WSL/Windows fall back to manual invocation.

OPS ► DAEMON

Diagnostic + auto-fix surface for the background ops-daemon process. Acts like ops-doctor but scoped to the one subsystem users actually see break: the launchd daemon that keeps briefing-pre-warm, memory-extractor, message-listener, inbox-digest, and competitor-intel alive.

CLI/API Reference

bin/ops-daemon-manager.sh

CommandUsageOutput
${CLAUDE_PLUGIN_ROOT}/scripts/ops-daemon-manager.sh statusEmit JSON snapshot{os, installed, running, pid, plist_version_match, health_fresh, ...}
${CLAUDE_PLUGIN_ROOT}/scripts/ops-daemon-manager.sh installFirst-time install (idempotent)Writes plist, loads launchd
${CLAUDE_PLUGIN_ROOT}/scripts/ops-daemon-manager.sh upgradeRe-point plist at current PLUGIN_ROOT + reloadFixes stale version paths
${CLAUDE_PLUGIN_ROOT}/scripts/ops-daemon-manager.sh restartUnload + reload without reconfiguringClears stuck state
${CLAUDE_PLUGIN_ROOT}/scripts/ops-daemon-manager.sh uninstallStop + remove plistReturns system to pre-install state

Accepts --plugin-root PATH to override auto-detection and --dry-run to preview without side effects.

Health file schema

${CLAUDE_PLUGIN_DATA_DIR}/daemon-health.json:

{
  "timestamp": "<ISO-8601 UTC>",
  "pid": <int>,
  "uptime_seconds": <int>,
  "services": {
    "<name>": {
      "status": "running|polling|scheduled|dead|needs_reauth",
      "pid": <int|null>,
      "last_health": "<string|null>",
      "last_run": "<ISO-8601|empty>",
      "next_run": "<ISO-8601|empty>",
      "restarts": <int>
    }
  },
  "action_needed": null | {"kind": "...", "service": "...", "message": "..."}
}

A healthy daemon refreshes this file every 30s. An mtime older than 120s is a strong fail signal.

---

Your task

Route on the first argument:

ArgumentAction
check (default)Run all diagnostics, print a colored report, exit 0 if green / 1 otherwise
fixRun check, then per detected issue ask the user for confirmation and apply the fix
restartCall ops-daemon-manager.sh restart
statusPrint the JSON output of ops-daemon-manager.sh status verbatim — consumed by other skills
uninstallAsk [Uninstall] / [Cancel] via AskUserQuestion, then call the manager

Diagnostic checklist

Run each check and track results as pass / fail / warn:

1. Plugin root resolvedCLAUDE_PLUGIN_ROOT env var set OR ~/.claude/plugins/cache/ops-marketplace/ops/<version>/scripts/ops-daemon.sh exists. 2. OS supporteduname -s is Darwin. On Linux/WSL print the manual invocation and exit 0 with a warn note. On native Windows print "not supported". 3. Plist installed~/Library/LaunchAgents/com.claude-ops.daemon.plist exists. 4. Plist points at current version — the second <string> inside ProgramArguments equals ${PLUGIN_ROOT}/scripts/ops-daemon.sh. Mismatch = stale after upgrade (the most common failure mode). 5. Plist is valid XMLplutil -lint passes. 6. Launchctl registeredlaunchctl list shows the label with a real PID (not -). 7. Process alivekill -0 <pid> succeeds. 8. Bash binary exists — the first <string> in ProgramArguments is executable and reports BASH_VERSINFO >= 4 (required for declare -A in the daemon script). 9. Health file freshdaemon-health.json exists, mtime within last 120 seconds. 10. Every service has a command — iterate daemon-services.json services; each enabled entry must have a non-empty command field. Missing command silently skips the service (historical bug). 11. Running services alive — for each service in the health file with status=running|polling, verify kill -0 <pid> succeeds. 12. Cron services have future `next_run`scheduled services must have a next_run timestamp in the future. 13. wacli-sync path resolves — if enabled, ~/.wacli/.health exists and is fresh. (Optional — mark warn not fail if missing.) 14. No zombie children — no orphaned ops-message-listener.sh or wacli-keepalive.sh processes without a parent ops-daemon.sh.

Fix playbook

For each failed check, fix mode proposes a specific repair and asks the user with AskUserQuestion (max 4 options — always include [Skip]):

FailureFixDestructive?
Plist stale version pathops-daemon-manager.sh upgradeYes — unloads + reloads
Plist missingops-daemon-manager.sh installNo
Plist invalid XMLRegenerate via install (after backup)Yes — overwrites
Process dead but plist okops-daemon-manager.sh restartYes — restarts
Health file stale (>120s)ops-daemon-manager.sh restartYes
Service missing commandMerge from scripts/daemon-services.example.json into user's daemon-services.json after showing a diffYes — writes config
Bash binary missing/<4brew install bash on macOS; on Linux check $(command -v bash) version; ask user to installNo (reports only)
Zombie child processeskill <pid> with per-process confirmation (Rule 5)Yes
Services config corrupt JSONRestore from scripts/daemon-services.default.json after confirmation + backupYes

Never batch fixes. Per Rule 5, each destructive action needs its own AskUserQuestion with [Apply] / [Skip] options.

Output format for check

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 OPS ► DAEMON CHECK
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 OS:           macos
 Plugin root:  ${CLAUDE_PLUGIN_ROOT}
 Daemon PID:   57004
 Uptime:       1h 12m

 ✓ Plist installed
 ✓ Plist points at current version
 ✓ Plist is valid XML
 ✓ Launchctl registered, PID alive
 ✓ Bash binary found (5.3)
 ✓ Health file fresh (mtime 23s ago)
 ✓ All 5 enabled services have commands
 ✓ Running services alive
 ✓ Cron services have future next_run

 STATUS: GREEN — daemon healthy

On failure, replace with and append a one-line remediation hint. Exit 1 so /ops:ops-status can surface red.

Output format for status

Print the JSON from ops-daemon-manager.sh status verbatim. No wrapping. This is the machine-readable contract consumed by ops-status, ops-go, and other skills.

Output format for fix

Render the check report, then for each failing check enter a confirmation loop:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 OPS ► DAEMON FIX — 3 issues found
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 ✗ Plist points at old version 1.0.0
   → Proposed: ops-daemon-manager.sh upgrade

Then AskUserQuestion with [Apply fix] / [Skip this issue] / [Cancel all]. Repeat for each issue. After all actions, re-run check and print a before/after diff.

Cross-OS notes

  • macOS: full support via launchd. All subcommands available.
  • Linux / WSL: ops-daemon-manager.sh install exits EX_UNAVAILABLE (69) and prints the manual nohup invocation. check still validates the daemon script and services config.
  • Windows native: unsupported. Use WSL.

Do not hardcode launchctl in this SKILL — always route through the manager script so future systemd / Task Scheduler support is a one-line addition.

Examples

# Morning habit: confirm the daemon survived overnight
/ops:daemon check

# After a plugin upgrade (`/plugin upgrade claude-ops`):
/ops:daemon fix
# → detects stale plist, asks [Apply upgrade], reloads, verifies

# Embedded in another skill:
/ops:daemon status | jq -r '.health_fresh'

Related skills

DevOps & CI/CDmonitoringinfra

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.