Ops Daemon logo

Ops Daemon

Organization
Lifecycle-Innovations-Limited
ops-daemon

OPS on-demand: This skill should be used when the user asks to "daemon health", "background services…

Overview

PublisherLifecycle-Innovations-Limited
Repositoryclaude-ops
Skill nameops-daemon
Stars
543
Forks
64
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by Lifecycle-Innovations-Limited on GitHub. Read the source before you install it.

Installation

Install the Ops Daemon AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/Lifecycle-Innovations-Limited/claude-ops/tree/main/claude-ops/skills/ops-daemon
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/Lifecycle-Innovations-Limited/claude-ops.git /tmp/claude-ops
mkdir -p .claude/skills
cp -r /tmp/claude-ops/claude-ops/skills/ops-daemon .claude/skills/ops-daemon
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Ops Daemon in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Ops Daemon on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Ops Daemon is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

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

Load ops-rules before acting. Public repo (no personal data). Outbound: one draft → one approval → one send. If AskUserQuestion / Workflow are missing, follow Rule 10 in ops-rules (Hermes: numbered options / two-turn Telegram card; delegate_task).

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

scripts/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:

json
{
  "timestamp": "<ISO-8601 UTC>",
  "pid": <int>,
  "uptime_seconds": <int>,
  "services": {
    "<name>": {
      "status": "running|polling|scheduled|dead|needs_reauth|max_restarts_exceeded",
      "pid": <int|null>,
      "last_health": "<string|null>",
      "last_run": "<ISO-8601|empty>",
      "next_run": "<ISO-8601|empty>",
      "restarts": <int>,
      "latency_ms": <int>,
      "last_success": "<ISO-8601|empty>",
      "error_count": <int>,
      "last_error": "<string|null>"
    }
  },
  "action_needed": null | {"kind": "...", "service": "...", "message": "..."},
  "credential_warnings": ["<string>", ...],
  "rate_limit_warnings": ["<string>", ...]
}

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

Per-service fields (Phase 16 additions):

  • latency_ms — duration of the most recent run for warm/cron services, in milliseconds. 0 when no run has occurred yet.
  • last_success — ISO-8601 UTC of the last clean run (no errors). Empty until the first success.
  • error_count — cumulative error count since daemon start. Reset on daemon restart.
  • last_error — truncated (≤300 chars) message from the most recent failure. null when there have been no failures.

Top-level fields (Phase 16 additions):

  • credential_warnings — list of credentials that are expiring within 7 days or are keys older than 180 days. Populated from offline inspection of preferences.json (never a live API call).
  • rate_limit_warnings — list of integrations currently at ≥80% of their quota window. Populated from rate-limits.json counters.

Persistent service failure: a service that hits max_restarts_exceeded status dispatches a one-shot HIGH severity push notification via ops-notify.sh to every configured sink (Telegram / Discord / ntfy / Pushover / macOS). The notification is re-armed the moment the service returns to running, so subsequent regressions still notify.

Smart Cache Invalidation (git hooks)

Cache timestamp files (.briefing_ts, .projects_ts, .marketing_ts, .prs_ts, .ci_ts) are deleted on local git commit and git merge so the next daemon warm cycle refreshes those specific caches without waiting for the normal throttle window.

Install:

bash ${CLAUDE_PLUGIN_ROOT}/scripts/ops-install-git-hooks.sh

Preview without writing:

bash ${CLAUDE_PLUGIN_ROOT}/scripts/ops-install-git-hooks.sh --dry-run

Remove:

bash ${CLAUDE_PLUGIN_ROOT}/scripts/ops-install-git-hooks.sh --uninstall

The installer is idempotent and only touches the block between # BEGIN ops-daemon-invalidate and # END ops-daemon-invalidate — existing husky / lefthook / pre-commit content in .git/hooks/post-commit or .git/hooks/post-merge is preserved.

Marketing Pre-Warm

The opt-in marketing-prewarm cron service pre-fetches cross-platform marketing data (Klaviyo, Meta Ads, GA4, GSC, Google Ads) every 15 minutes so /ops:marketing loads instantly from cache. Disabled by default; enable with /ops:setup marketing once marketing credentials are configured.

Rate Limit Tracking

Per-integration counters in ${CLAUDE_PLUGIN_DATA_DIR}/rate-limits.json — {quota, calls, window_start, warned_80pct} per integration. On each tracked API call the daemon advances the rolling window, increments the counter, and sends a single MEDIUM push notification when the ratio crosses 80%. Windows reset automatically on rollover, which re-arms the 80% warning.

Override the seeded defaults by setting rate_limit_quotas in ${CLAUDE_PLUGIN_DATA_DIR}/preferences.json:

json
{
  "rate_limit_quotas": {
    "meta_ads": { "quota": 200, "window_seconds": 3600 },
    "klaviyo": { "quota": 75, "window_seconds": 60 }
  }
}

Credential Rotation Alerts

The daemon checks ${CLAUDE_PLUGIN_DATA_DIR}/preferences.json once an hour for:

  • <integration>_expires_at — ISO-8601 timestamp or the literal string "never". Warns when within 7 days of expiry.
  • <integration>_created_at — ISO-8601 timestamp of when an API key was last created/rotated. Warns once the key is 180 days old.

The check is entirely offline — it never makes a network call. Warnings surface in daemon-health.json as credential_warnings and trigger a MEDIUM push notification once per (credential, day) tuple. /ops:fires lists them alongside Sentry / infra / CI issues.


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 resolved — CLAUDE_PLUGIN_ROOT env var set OR ~/.claude/plugins/cache/ops-marketplace/ops/<version>/scripts/ops-daemon.sh exists.
  2. OS supported — uname -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 XML — plutil -lint passes.
  6. Launchctl registered — launchctl list shows the label with a real PID (not -).
  7. Process alive — kill -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 fresh — daemon-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. whatsapp-bridge running — if enabled, lsof -i :8080 | grep LISTEN returns a result. (Optional — mark warn not fail if missing.)
  14. No zombie children — no orphaned ops-message-listener.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'

Frequently asked questions

What does the Ops Daemon AI skill do?

OPS on-demand: This skill should be used when the user asks to "daemon health", "background services…

Why use Ops Daemon on TypingMind?

Because you install it once and use it with any model. Ops Daemon is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Ops Daemon in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/Lifecycle-Innovations-Limited/claude-ops/tree/main/claude-ops/skills/ops-daemon. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Ops Daemon?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Ops Daemon?

As many as you like. As long as a model supports skills, you can use Ops Daemon with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Ops Daemon AI skill free?

Yes. It is published on GitHub by Lifecycle-Innovations-Limited under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇