add (schedule validated by systemd-analyze, units + script printed), list (next elapse + last result), run, logs, rm. Command stored as a script so quoting never meets ExecStart; PATH includes ~/.local/bin so agent tools resolve. cronr-* namespace guards foreign units. Smoked live: add -> run -> journal -> rm. Spec: doc/tool-parity.md 3.1. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011KikHkfCiC3yELbsMN8fT9
cronr — agent scheduling via systemd user timers
Lets an agent create recurring or one-shot jobs that survive session
exit and reboot — what agy's in-memory schedule tool and Claude's
in-session wakeups cannot do. No daemon: systemd runs the jobs, cronr
just manages namespaced cronr-<name> units. Closes the
CronCreate/List/Delete gap from
doc/tool-parity.md §3.1.
Usage
cronr add <name> --schedule "OnCalendar spec" --cmd "shell command"
cronr add <name> --at "YYYY-MM-DD HH:MM" --cmd "shell command" # one-shot
cronr list # schedule, next run, last result per job
cronr run <name> # run the job right now (timer untouched)
cronr logs <name> [--lines N] # the job's journal
cronr rm <name> # disable and delete
Examples:
cronr add nightly-ci --schedule "*-*-* 07:00" --cmd 'agy -p "check CI status and notify"'
cronr add backup-ping --schedule "Mon *-*-* 09:00" --cmd 'notifyr send --msg "weekly backup check"'
cronr add once --at "2026-08-10 03:00" --cmd 'systemctl --user restart helmd'
How it works
add writes three files and prints all of them, so the result is
fully verifiable:
~/.local/share/cronr/<name>.sh— the command, verbatim (shell quoting never meets systemd's ExecStart parsing)~/.config/systemd/user/cronr-<name>.service— oneshot, with~/.local/binon PATH so agent tools (notifyr, svgc, agy…) resolve~/.config/systemd/user/cronr-<name>.timer—OnCalendar=…,Persistent=truefor recurring jobs (missed runs fire on next boot)
Schedules are validated by systemd-analyze calendar before anything
is written — you get systemd's own error text plus the computed next
elapse. list/rm only ever see cronr-* units, so other services
are untouchable by construction.
cronr run <name> starts the service immediately — handy for testing
a job before trusting the schedule.
Build & test
go test ./...
go build -o build/cronr .