WATCHD
SCHEDULE AI AGENTS
FIG. 01 / THE OUTCOME

Wake up to what changed. 

Agents are markdown files. watchd runs them on schedule, remembers what they found, and gates what they touch.

SINGLE GO BINARYZERO CONFIGMIT
agents/competitor.mdARMED
00:30uptime$0.008all healthy, 142ms01:00errors$0.0213 new timeouts in payment worker, same root cause02:00security$0.214raw SQL in new search endpoint — flagged04:15competitor$0.041Acme cut Pro pricing 20%05:30dbhealth$0.063idx_sessions_legacy unused for 30d06:00digest$0.089morning brief compiled from 5 agents
FIG. 02 / ONE NIGHTSCROLL TO ADVANCE
LOCAL TIME
23:00

While you sleep, the scheduler keeps the watch.

You slept. They didn't.
4 FINDINGS · 5 RUNS · $0.35 TOTAL
23:08» watchd up
5 agents armed. waiting for schedules.
00:30 uptime$0.008
All healthy. 200 OK in 142ms.
02:00 security$0.214
New commit adds raw SQL in /search. Flagged with a patch suggestion.
04:15 competitor$0.041
Acme cut Pro pricing 20%. Second cut this quarter — reading as a price war.
06:00 digest$0.089
Morning brief compiled. 3 findings, 1 plan pending your approval.
FIG. 03 / PROOFREAL OUTPUT

Write markdown. The model does the rest. 

YAML frontmatter sets the schedule, model, and budget. The markdown body is the prompt. watchd runs claude -p, parses the JSON output, and records every run with its cost and a hash of the exact instructions that produced it.

AGENT FILE
agents/uptime.md
---
name: uptime
schedule: 5m
model: haiku
max_turns: 5
budget: 0.10
---

# Uptime Monitor

Check if https://api.myapp.com/health
returns 200. If not, tell me what's wrong.
CLI OUTPUT
watchd run + watchd status
$ watchd run uptime
running uptime...
✓ uptime in 4.2s ($0.0089)
The endpoint returned HTTP 200 with response
time of 142ms. All healthy.

$ watchd
AGENT      SCHEDULE  STATUS   COST      LAST RUN
uptime     5m        success  $0.0089   2m ago
digest     1d        success  $0.1204   6h ago
COST TRACKING
watchd costs + watchd logs
$ watchd costs
AGENT          COST     RUNS
uptime       $ 0.2314     26
digest       $ 0.4816      4
security     $ 0.8201      7
TOTAL        $ 1.5331     37

$ watchd logs uptime
✓ uptime   success  4.2s  $0.0089  2m ago
  All healthy. 200 OK in 142ms.
✓ uptime   success  3.8s  $0.0076  7m ago
  All healthy. 200 OK in 138ms.
FIG. 04 / MEMORYmemory: true

Loops that compound. 

One line of frontmatter gives an agent a memory file it owns: injected at the start of every run, updated before it finishes. A scan that re-reports the same findings is noise. One that remembers builds intelligence.

RUN 0123:30
memory/competitor.md — memory is empty — the agent writes a baseline
## Baseline — 3 competitors
- Acme: Pro $49/mo, AI addon beta
- Initech: usage-based, no free tier
- Globex: enterprise only, POC req'd
RUN 0205:30
memory/competitor.md — reads the baseline, reports only the delta
## Baseline — 3 competitors
- Acme: Pro $49/mo, AI addon beta
- Initech: usage-based, no free tier
- Globex: enterprise only, POC req'd
+ 06-09: Acme launches annual billing
+ Initech free tier rumored (HN)
RUN 0311:30
memory/competitor.md — connects runs into a trend you can act on
## Baseline — 3 competitors
- Acme: Pro $49 -> $39 (-20%)
- Initech: usage-based, no free tier
- Globex: enterprise only, POC req'd
- 06-09: Acme launches annual billing
+ 2nd Acme price cut this quarter
+ pattern: price war forming.
+ watch for the Globex response
NOT RAW TRANSCRIPT STUFFING — THE AGENT CURATES ITS OWN NOTES, SO CONTEXT STAYS SHARP AND INJECTION SURFACE STAYS SMALL
FIG. 05 / THE GATEgate: true

Safe to point at real systems. 

With gate: true the first pass runs with read-only tools, ends with a concrete plan, and lands in watchd pending. Nothing executes until you approve. notify pings you wherever you are — the plan reaches you instead of waiting to be noticed.

---
name: dbcleanup
schedule: 1d
model: sonnet
gate: true
notify: "ntfy pub alerts 'watchd: $WATCHD_AGENT \
$WATCHD_STATUS'"
---
 
# DB Cleanup
 
Find bloated tables, unused indexes, and
rows older than the retention policy.
Propose a cleanup plan.
$ watchd pendingAWAITING APPROVAL
ID    AGENT      STATUS
a3f9  dbcleanup  pending (2m ago)
PLAN — READ-ONLY PASS
1. VACUUM ANALYZE on 4 bloated tables
2. Drop unused index idx_sessions_legacy
3. Archive 48,210 rows >180d from events
APPROVING RESUMES THE SAME SESSION WITH THE AGENT'S REAL PERMISSIONS. TRY IT ↑
FIG. 06 / WHY NOT CRON + BASH

Cron runs scripts. watchd runs judgment. 

watchd wraps claude -p with scheduling, budgets, run history, memory, and an approval gate. Your agents are markdown files, not bash scripts.

CRON + BASH
Write a bash script. Parse output yourself. No structure.
No cost tracking. You find out at the end of the month.
No run history. stdout is gone when the terminal closes.
Your script runs with your full permissions. Hope it behaves.
No memory. Every run starts from zero and re-reports.
WATCHD
Write a markdown file. The model handles the thinking.
Cost tracked per run. Budgets enforced mid-run.
Full run history with prompt provenance hashes.
gate: true — plan first, execute only after you approve.
memory: true — runs build on each other and compound.
FIG. 07 / RECIPES6 AGENTS

Agents you can run tonight. 

Each agent is a markdown file. Drop it in agents/, run watchd up.

Uptime monitor

Check your endpoints every 5 minutes. The model interprets the response, not just the status code.

---
name: uptime
schedule: 5m
model: haiku
budget: 0.10
---
Check if https://api.myapp.com/health
returns 200. If the response time is
above 500ms or the body looks wrong,
explain what might be happening.
Security scanner

Audit recent commits and get pinged the moment something looks wrong.

---
name: security
schedule: 6h
model: sonnet
max_turns: 15
budget: 1.00
notify: "ntfy pub alerts ..."
---
Check the latest commits in my repo
for security issues: SQL injection,
hardcoded secrets, unsafe file ops.
Flag anything that needs attention.
Inbox digest

Summarize what matters from your inbox. Runs before you wake up.

---
name: inbox
schedule: 1d
model: sonnet
budget: 0.50
---
Check my unread emails from the
last 24 hours. Summarize anything
from customers or investors.
Ignore newsletters and marketing.
Changelog writer

Generate release notes from your git log. Push to docs automatically.

---
name: changelog
schedule: 1d
model: sonnet
max_turns: 10
---
Look at git commits from the last
24 hours. Write a concise changelog
entry. Group by feature, fix, chore.
Skip merge commits and CI changes.
Error log analyzer

Remembers past incidents, so it reports new patterns instead of repeating old ones.

---
name: errors
schedule: 30m
model: sonnet
budget: 0.10
memory: true
---
Read the last 100 lines of
/var/log/app/error.log.
Group similar errors, identify
root causes. Build on what you
already know — report only deltas.
DB maintenance

Plans destructive work in read-only mode. Executes only after you approve.

---
name: dbcleanup
schedule: 1d
model: sonnet
budget: 0.50
gate: true
---
Find bloated tables, unused indexes,
and rows older than retention policy.
Propose a cleanup plan with exact
commands and expected impact.
FIG. 08 / UNDER THE HOODSINGLE BINARY

One Go binary. The model does the thinking. 

watchd is a thin orchestration layer. No AI runtime, no model loading, no API keys to manage. It spawns claude -p and parses the JSON output. Every run records prompt_hash and agent_hash, so you can always answer "which instructions produced this output."

cmd/watchd
Entry point. One binary, no runtime deps.
internal/cli
init, add, run, logs, costs, pending, approve, up
internal/agent
Parses markdown agents + YAML frontmatter
internal/runner
Spawns claude -p, parses JSON events
internal/store
Run history as JSON files with provenance hashes
internal/daemon
Scheduler loop for recurring agents
cli -> runnercli -> storecli -> agentcli -> daemondaemon -> runnerrunner -> agentrunner -> store
FIG. 09 / GET STARTED2 MINUTES

Tonight, then every night. 

Star on GitHub
BUILT BY © LEVEL09