> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wolffi.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Heartbeat & Scheduling

> Configure autonomous scheduled tasks with the brainstem heartbeat

# Autonomous Jobs on a Timer

The heartbeat is how Wolffish does things on its own — a morning briefing at 8, an inbox sweep every 15 minutes, a one-off reminder in 2 days. Jobs live in `brain/brainstem/heartbeat.md`, parsed by the brainstem module and run through the full agent pipeline when they fire.

You rarely edit this file by hand. Just ask Wolffish — *"every morning, summarize my unread emails"* or *"in 2 days remind me to renew my domain"* — and it creates, edits, and removes jobs for you through its **`automations`** capability (`automation_list`, `automation_create`, `automation_edit`, `automation_delete`, `automation_check`, `automation_run`). Hand-editing still works, and the format is below.

## How It Works

Each `##` heading in `heartbeat.md` defines a job. **The heading *is* the schedule** (e.g. `## Daily (08:00)`) — there's no separate job name. The body below it is the instruction, sent to the agent as a user message when the schedule fires.

```markdown theme={null}
## Daily (08:00)

Summarize my unread emails and calendar events for today.
List any GitHub notifications. Keep it brief.

## Every (30m)

Check my open pull requests on GitHub. If any have new
reviews or comments, give me a one-line summary of each.
```

## Schedule Formats

All times use your system's local timezone, 24-hour format. There's no UTC conversion — `Daily (09:00)` means 9 AM wherever you are.

### One-time (runs once, then deletes itself)

| Format                            | Meaning                                 | Example                            |
| --------------------------------- | --------------------------------------- | ---------------------------------- |
| `Once (YYYY-MM-DD HH:MM)`         | Once, at an absolute local date-time    | `Once (2026-12-31 23:30)`          |
| `In (Nm)` / `In (Nh)` / `In (Nd)` | Once, N minutes / hours / days from now | `In (15m)` · `In (2h)` · `In (2d)` |

After a one-time job runs, it **removes its own entry** from the file. `In (...)` is shorthand you use when *asking* Wolffish — it's converted to an absolute `Once (...)` at creation (a relative delay can't survive a restart), so what lands in the file is always a `Once (...)`. Hand-writing `In (...)` directly isn't supported; use `Once (...)` for an exact time.

### Recurring (fires until you remove it)

| Format               | Meaning                                       | Example                 |
| -------------------- | --------------------------------------------- | ----------------------- |
| `Startup`            | Runs once each time the brainstem initializes | `Startup`               |
| `Every (Nm)`         | Repeating interval in minutes                 | `Every (5m)`            |
| `Every (Nh)`         | Repeating interval in hours                   | `Every (2h)`            |
| `Hourly (MM)`        | Once per hour at minute mark                  | `Hourly (30)`           |
| `Daily (HH:MM)`      | Once per day                                  | `Daily (09:00)`         |
| `Nightly (HH:MM)`    | Once per day (alias for Daily)                | `Nightly (23:00)`       |
| `Weekday (HH:MM)`    | Monday through Friday only                    | `Weekday (08:30)`       |
| `Weekly (Day HH:MM)` | Once per week on a named day                  | `Weekly (Monday 09:00)` |
| `Monthly (DD HH:MM)` | Once per month on a day number                | `Monthly (1 10:00)`     |
| `Cron (expression)`  | Raw 5-field cron syntax                       | `Cron (*/15 * * * *)`   |

<Info>
  Out-of-range schedules are rejected up front — `Every (0m)`, `Daily (99:99)`, or a `Once (...)` in the past won't be silently accepted and then never fire. If you hand-edit a malformed heading, it shows up flagged when Wolffish lists your automations.
</Info>

## Job Execution

Heartbeat jobs run through the full agent pipeline — same brain, same capabilities, same memory. What differs from a normal conversation:

* **Auto-approval**: Tool calls bypass amygdala confirmation (no approval dialogs).
* **Sealed conversation**: Each run creates its own conversation, visible in history.
* **No streaming**: Responses are generated in the background without UI interruption.

<Warning>
  Because heartbeat jobs auto-approve every tool call, be careful what you schedule. A job that says "delete old files" will execute without asking. Write defensive instructions — "list files older than 30 days and tell me what you'd delete" beats "delete files older than 30 days." See [What to Schedule](/configuration/what-to-schedule) for the full safety decision layer.
</Warning>

### One at a time, queued — never dropped

Jobs run **one at a time**. If a job fires while another is still running, it **queues** and runs next rather than being skipped. The queue is coalesced per job, so a slow job can't pile up a backlog of its own ticks. You don't need to spread jobs out to avoid collisions.

### Missed runs catch up

If Wolffish was closed when a job was due, it runs once on the next launch — **collapsed**: a recurring job that missed several fires during the downtime runs a *single* catch-up, not one per missed tick. Only misses within the last **24 hours** are replayed; older ones are dropped. A one-time job past its time runs if it's within that window, then deletes itself; if it's older, it's quietly retired without running.

## Managing Jobs

### Through Wolffish (recommended)

Just talk to it:

* *"What automations do I have?"* → lists them with their schedule and last-run status
* *"Every weekday at 7:45, give me a morning briefing"* → creates a recurring job
* *"In 2 days, remind me to renew my domain"* → creates a one-time job that self-deletes
* *"Change the morning briefing to 8am"* / *"Delete the PR watcher"* → edits or removes
* *"Run my email check now"* → fires a job immediately to test it

Changes apply live — the brainstem reloads the schedule as soon as the file changes, no restart needed.

### By hand

Edit `heartbeat.md` directly. To **disable** a job without deleting it, comment it out with HTML comments:

```markdown theme={null}
## Daily (08:00)

Summarize my unread emails and calendar events for today.

<!--
## Every (1h)

This job is disabled and won't run.
-->
```

<Tip>
  The brainstem watches `heartbeat.md` and reloads on save, so hand edits take effect without restarting. The commented examples shipped in the file are a menu — uncomment one to activate it.
</Tip>

## Practical Examples

### Morning Briefing

```markdown theme={null}
## Weekday (07:45)

Give me a morning briefing:
1. Unread emails — summarize the important ones
2. Today's calendar — list meetings with times
3. GitHub — any PRs that need my review
4. Weather — current conditions and forecast

Keep each section to 2-3 lines max.
```

### Email Triage

```markdown theme={null}
## Every (2h)

Check my email for anything urgent or time-sensitive.
If you find something that needs immediate attention,
flag it and write a one-sentence summary.
Ignore newsletters and marketing emails.
```

### PR Monitoring

```markdown theme={null}
## Every (30m)

Check my open pull requests on GitHub.
Report only PRs with new activity since your last check:
- New reviews or approvals
- CI status changes (especially failures)
- New comments or requested changes

If nothing changed, respond with "No PR updates."
```

### One-time Reminder

```markdown theme={null}
## Once (2026-12-31 23:30)

Wish me a happy new year and give me a short recap of my
biggest wins this year, drawn from my episodes and knowledge.
```

This fires once at 11:30 PM on Dec 31, then removes itself from the file.

## Memory Compaction

Memory compaction (hippocampus consolidation) is a separate scheduled process configured in **Settings > Hippocampus > Compaction**, not in `heartbeat.md`. The brainstem runs it on its own daily/weekly schedule, and it won't appear when Wolffish lists your automations.

<Info>
  Compaction consolidates daily episodes into weekly summaries and promotes important information to knowledge files. It runs independently of heartbeat jobs.
</Info>

## Full Example File

```markdown theme={null}
# Heartbeat

## Startup

Run a quick health check. Verify that all configured
providers are reachable and report any issues.

## Weekday (07:45)

Give me a morning briefing:
1. Unread emails — summarize the important ones
2. Today's calendar — list meetings with times
3. GitHub — any PRs that need my review

## Every (30m)

Check my open pull requests on GitHub for new activity.
Only report changes since last check.

## Nightly (18:00)

Write a brief end-of-day summary of completed tasks
and pending items for tomorrow.

## Once (2026-12-31 23:30)

Wish me a happy new year and recap my biggest wins this year.
```

## See Also

* [What to Schedule](/configuration/what-to-schedule) — which workflows are safe to run autonomously, and how to make a risky one safe
* [Self-Authoring Skills](/capabilities/self-authoring-skills) — the sibling self-management capability
