Install
openclaw skills install heartbeat-cronCreate and refine HEARTBEAT.md files for murmur — a CLI daemon that runs scheduled Claude prompts on a cron or interval schedule. Use this skill when the user wants to set up a recurring automated action (e.g., "monitor my GitHub issues", "check Hacker News for AI articles", "watch my endpoints", "send me a daily digest"). Guides the user through an interview, drafts the heartbeat prompt, tests it, and registers it with murmur's scheduler. Triggers: heartbeat, murmur, recurring task, scheduled action, cron, monitor, watch, automate, periodic check, scheduled prompt.
openclaw skills install heartbeat-cronCreate well-crafted HEARTBEAT.md files for murmur through a structured interview, test run, and refinement loop.
Murmur is a minimal scheduler. It reads a HEARTBEAT.md file, sends its contents to Claude on a schedule, and classifies the response:
HEARTBEAT_OK — nothing to report (silent)ATTENTION: ... — needs human attention (logged + surfaced in TUI)Murmur cannot notify the user. It only runs the prompt and logs the result. If the user wants notifications (Slack, Telegram, push), the HEARTBEAT.md itself must include the delivery step. The heartbeat is the entire pipeline: gather data → decide → act → deliver.
Each heartbeat is stateless. Every run is a fresh Claude session with no memory of previous runs. For workflows that need to track changes over time (price deltas, last-checked timestamps), use files in the workspace as simple state stores (e.g., last-price.txt, tracking-state.json).
Sleep/wake behavior. When the machine sleeps, the daemon freezes — no ticks fire. On wake, overdue jobs run immediately but multiple missed runs collapse into a single catch-up execution (not one per missed interval). This is correct for heartbeat-style tasks: you want to check current state, not replay missed checks. If the user needs reliable scheduling, advise them to disable sleep on their machine (see FAQ in README).
Every heartbeat is a markdown file with an optional YAML frontmatter block. Frontmatter values take precedence over config.json.
---
interval: 1h # or cron: "0 9 * * 1-5" (pick one)
# tz: America/New_York # timezone for cron (default: local system tz)
# timeout: 15m # max run time (default: 5m)
# agent: claude-code # "claude-code" (default), "codex", or "pi"
# model: opus # model hint passed to the agent
# maxTurns: 50 # cap agent iterations per run (default: 99)
# name: My Heartbeat
# description: What this heartbeat does
# session: my-session # pi-specific: reuse a named browser session
# sandbox: workspace-write # codex-specific: "read-only", "workspace-write", or "danger-full-access"
# networkAccess: false # codex-specific: allow outbound network in workspace-write sandbox
# permissions: skip # skip permission checks (only "skip" supported in frontmatter)
---
Your prompt here...
Notes:
interval or cron — use one, not both. Intervals: 15m, 1h, 6h, 1d. Cron: standard 5-field expressions.permissions: "skip" is the only permissions value supported in frontmatter. For deny lists, use config.json.murmur init generates a template with these fields pre-filled.Before starting, verify murmur is installed:
which murmur
brew install t0dorakis/murmur/murmur
If Homebrew isn't available, install from source:
git clone https://github.com/t0dorakis/murmur.git
cd murmur && bun install && bun run build
# Then add ./murmur to PATH
You can also scaffold a workspace immediately with flags:
murmur init {path} --interval 30m
murmur init {path} --cron "0 9 * * 1-5" --timeout 15m
murmur init {path} --template github-digest # Use a starter template
Multiple heartbeats per repo — Use --name to create heartbeats in a heartbeats/ directory:
murmur init {path} --name issue-worker --interval 30m
murmur init {path} --name deploy-monitor --cron "0 9 * * 1-5"
This creates heartbeats/<name>/HEARTBEAT.md inside the workspace. All heartbeats share the repo root as CWD. A root HEARTBEAT.md still works alongside named heartbeats.
Conduct a focused interview using AskUserQuestion. Go one or two questions at a time, building on previous answers.
Round 1 — The goal:
Ask what they want automated. If they're unsure or exploring, read references/examples.md for inspiration across categories: code/repos, research/intelligence, ops/infrastructure, personal/creative. Suggest examples that match their context.
Round 1b — Tool discovery:
Before diving into details, check whether the user's goal needs tools beyond what's already installed. Run a web search to find relevant CLIs, MCP servers, or agent skills that could help.
Browser tools — Many valuable heartbeats need to interact with real websites (checking prices, monitoring pages, logging into portals). Claude's built-in WebFetch works for simple static pages, but sites with JavaScript rendering, login flows, or anti-bot measures need a real browser:
agent: pi.Other tools — Search the web for: "{user's goal}" CLI tool or "{user's goal}" MCP server or check skills.sh for community skills. Examples:
gh CLI is installedTell the user what you found and recommend installing anything that would make the heartbeat more capable.
Round 2 — The details:
Based on their goal, dig into specifics:
15m, 1h, 6h, 1d0 9 * * 1-5 (weekdays at 9am), */30 * * * * (every 30 min)timeout: 15m for long-running tasks)model: opus, model: sonnet, etc.)claude-code (default) runs Claude Code CLI; codex runs OpenAI Codex CLI (uses sandbox policies); pi runs the pi agent (has browser extensions)Round 3 — Delivery:
This is critical. Ask how they want results delivered. Options:
Remind them: murmur is just a scheduler — it won't forward anything. If they want to be notified, the heartbeat itself must do the notifying.
Round 3b — Credentials (if needed):
If delivery or data sources need tokens/webhooks:
.env in the workspace are available (Bun auto-loads them).env, referenced as $VAR_NAME in the heartbeatWrite the HEARTBEAT.md file. Rules:
interval or cron). Add timeout, model, or other fields as needed based on the interview.last-price.txt, tracking-state.json){placeholder} left behind)$VAR_NAME for secretsPlace the file at {workspace}/HEARTBEAT.md for single-heartbeat workspaces, or {workspace}/heartbeats/{name}/HEARTBEAT.md for multi-heartbeat repos.
Run one heartbeat to verify:
murmur beat {workspace_path}
# Or for a named heartbeat:
murmur beat {workspace_path} --name {name}
Show the user the outcome and output.
Ask the user: "Did that do what you expected?"
Register the workspace with murmur so the daemon knows about it:
murmur init {absolute_workspace_path} — this auto-registers the workspace in ~/.murmur/config.json (with { path, lastRun: null }). If HEARTBEAT.md already exists, it skips creating it but still registers.murmur workspaces list~/.murmur/config.json directly if you need a permissions.deny list (frontmatter only supports permissions: skip).murmur start — foreground with TUI (press q to quit, d to detach)murmur start --detach — background mode (reattach with murmur watch){placeholder} values in the final HEARTBEAT.mdmurmur beat before declaring doneheartbeats/ directory with --name.15m for uptime, 1h for active dev work, 6h–1d for digests/research. Use cron when the user wants specific times (e.g., 0 9 * * 1-5 for weekday mornings).