Blog
ENPL

claudeclaw + cron — Claude as an assistant with its own schedule

Claude Code can work even when I'm not driving. claudeclaw is the mechanism that schedules tasks for it — daily briefings, PR reviews, dependency audits. Showing how it works on my setup.

·5 min read
claudeclaw + cron — Claude as an assistant with its own schedule

The default Claude Code model is "I sit down, I ask, the agent answers." claudeclaw inverts that: the agent has its own calendar and pings me when it has something to say. I run four active cron jobs and a few one-shots, here's what it looks like and what I learned.

What is claudeclaw

A Claude Code plugin that adds:

  • a daemon holding state across sessions
  • a way to define jobs (cron expression + prompt + delivery)
  • Telegram integration for two-way comms
  • a heartbeat that confirms the daemon is alive

My config repository:

~/.openclaw/cron/
├── jobs.json          # job definitions
└── runs/
    ├── morning.jsonl  # run log
    └── ...

Each job is a JSON object:

{
  "id": "morning-briefing",
  "name": "Morning briefing",
  "agentId": "main",
  "enabled": true,
  "schedule": { "kind": "cron", "expr": "0 8 * * *", "tz": "Europe/Warsaw" },
  "payload": {
    "kind": "agentTurn",
    "message": "Check weather, today's calendar, backup status, latest emails (top 5). Short summary.",
    "lightContext": true
  },
  "delivery": { "mode": "announce", "channel": "telegram", "to": "5094102576" }
}

Job 1: morning briefing

Daily, 8 AM. The agent checks:

  • weather via Home Assistant (outdoor sensor)
  • Google Calendar (today's events)
  • backup status (Proxmox)
  • top 5 unread emails

Output goes to Telegram as a single ~150-word message. No filters, no parsing, the model decides what's relevant.

🌅 Good morning. 8°C, foggy until 11.
📅 Today: 14:00 meeting #1, 17:00 workout.
💾 VM backup proxmox: ✅ at 03:00.
📧 3 emails worth attention: invoice X (deadline tomorrow), ...

This replaces the "open four apps in the morning" ritual. Running for 4 months, reliably.

Job 2: post-merge code review

A GitHub webhook fires the job with a PR number. The agent:

  1. fetches the diff
  2. reads the project's CLAUDE.md (style context)
  3. runs the code-reviewer subagent
  4. sends the result to Telegram
{
  "id": "post-merge-review",
  "schedule": { "kind": "trigger", "via": "webhook" },
  "payload": {
    "kind": "agentTurn",
    "message": "Code review on PR ${PR_NUMBER} in ${REPO}. Focus on: consistency with existing style, security, no silent failures."
  }
}

It doesn't replace "real" review (the bot has no intent context), but it catches 1-2 nits per PR. On average.

Job 3: dependency audit

Weekly, Sunday 22:00. The agent does:

# Pseudocode for what it runs
for project in ~/projects/*; do
  cd "$project"
  npm audit --json
  pip-audit
done

Output: an aggregate of HIGH/CRITICAL CVEs, sorted by project. If zero, short "all clear" message. If something, list with links.

Often it's a false positive (a CVE'd package only in devDeps). But sometimes it catches a real issue before I notice. Worth it.

Job 4: backup status

Daily, 6 AM. Checks:

  • whether the Proxmox VM snapshot ran
  • whether obsidian-livesync (CouchDB) is current
  • whether the GitHub mirror works

Output is sent only when something is wrong. Key detail: silence means "all ok". I do not want 365 "backup OK" pings per year.

What I learned

1. Light context as the default. Each job starts a fresh session with no history. Simplifies debugging (each run is deterministic) and lowers cost. Full context only for things that genuinely need it (e.g. continuation).

2. Telegram > email for alerts. Email gets 200 a day, Telegram from a bot gets only from a bot. If something shows up there, I read it.

3. Cron expression isn't everything. I also have trigger-based jobs (GitHub webhook, callback from systemd). claudeclaw handles both. I use trigger more than cron.

4. Failover to Telegram. Every job notifies on failure. Not silent death, but "job X failed, log at Y." Earlier I had jobs that hadn't run for a month and I didn't know.

Anti-patterns

Three things I tried early and dropped:

1. "Smart" intervals. "Run the job when CPU < 30%." The agent handles models, not scheduling. Leave that to systemd timers.

2. One job, many responsibilities. I had "monitoring-everything" running 8 minutes. Split into 5 smaller ones, each < 90 seconds. Easier to debug, each has a clear owner.

3. Memory between runs. I tried passing state via a file. Ended with the agent reading it inconsistently. Now every run is stateless; if I need continuity, I use a db (sqlite) explicitly.

Minimum setup

If you want to try, the smallest sensible setup:

# 1. Install the plugin
claude plugin install claudeclaw
 
# 2. Create your first job (morning ping)
claude jobs create \
  --name "morning-ping" \
  --cron "0 8 * * *" \
  --message "Say good morning. Check if I have anything in the calendar today."
 
# 3. Status
claude jobs list

The first job works after one night. Once it becomes a habit, add more.


claudeclaw isn't sci-fi or an autonomous agent. It's plain cron with a wrapper that talks to me in plain language. That's enough for the agent to be useful while I sleep.