Heartbeat Creator Create well-crafted HEARTBEAT.md files for murmur through a structured interview, test run, and refinement loop. Context 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). HEARTBEAT.md Format 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. Workflow 0. Preflight Before starting, verify murmur is installed: which murmur Found → continue to interview. Not found → install via Homebrew: 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/
Or for a named heartbeat:
murmur beat { workspace_path } --name { name } Show the user the outcome and output. 4. Evaluate Ask the user: "Did that do what you expected?" No → refine the HEARTBEAT.md based on feedback, test again. Repeat until satisfied. Yes → proceed to register. 5. Register Register the workspace with murmur so the daemon knows about it: Run 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. Verify registration: murmur workspaces list Schedule, timeout, model, and other settings live in the HEARTBEAT.md frontmatter — no need to edit config.json for these. Only edit ~/.murmur/config.json directly if you need a permissions.deny list (frontmatter only supports permissions: skip ). Tell the user to start the daemon: murmur start — foreground with TUI (press q to quit, d to detach) murmur start --detach — background mode (reattach with murmur watch ) Rules Never leave {placeholder} values in the final HEARTBEAT.md Always test with murmur beat before declaring done Always ask the user to evaluate the test result If a heartbeat needs tools the user doesn't have installed, tell them what to install One heartbeat = one purpose. Multiple automations in the same repo = use heartbeats/ directory with --name . Schedule suggestions: 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).