Cron
Overview
Use this skill to manage Codex automations through the native Zig cron CLI. Runtime paths are Zig-only (no Python fallback, no shell launchd wrappers).
Zig CLI Iteration Repos
When iterating on cron , use these two repos:
-
skills-zig (/Users/tk/workspace/tk/skills-zig ): source for the cron binary, build/test wiring, release tags.
-
homebrew-tap (/Users/tk/workspace/tk/homebrew-tap ): formula/checksum updates for released binaries.
Quick Start
run_cron_tool() { install_cron_direct() { local repo="${SKILLS_ZIG_REPO:-$HOME/workspace/tk/skills-zig}" if ! command -v zig >/dev/null 2>&1; then echo "zig not found. Install Zig from https://ziglang.org/download/ and retry." >&2 return 1 fi if [ ! -d "$repo" ]; then echo "skills-zig repo not found at $repo." >&2 echo "clone it with: git clone https://github.com/tkersey/skills-zig "$repo"" >&2 return 1 fi if ! (cd "$repo" && zig build build-cron -Doptimize=ReleaseFast); then echo "direct Zig build failed in $repo." >&2 return 1 fi if [ ! -x "$repo/zig-out/bin/cron" ]; then echo "direct Zig build did not produce $repo/zig-out/bin/cron." >&2 return 1 fi mkdir -p "$HOME/.local/bin" install -m 0755 "$repo/zig-out/bin/cron" "$HOME/.local/bin/cron" }
local os="$(uname -s)" if command -v cron >/dev/null 2>&1 && cron --help 2>&1 | grep -q "cron.zig"; then cron "$@" return fi
if [ "$os" = "Darwin" ]; then if ! command -v brew >/dev/null 2>&1; then echo "homebrew is required on macOS: https://brew.sh/" >&2 return 1 fi if ! brew install tkersey/tap/cron; then echo "brew install tkersey/tap/cron failed." >&2 return 1 fi elif ! (command -v cron >/dev/null 2>&1 && cron --help 2>&1 | grep -q "cron.zig"); then if ! install_cron_direct; then return 1 fi fi
if command -v cron >/dev/null 2>&1 && cron --help 2>&1 | grep -q "cron.zig"; then cron "$@" return fi echo "cron binary missing or incompatible after install attempt." >&2 if [ "$os" = "Darwin" ]; then echo "expected install path: brew install tkersey/tap/cron" >&2 else echo "expected direct path: SKILLS_ZIG_REPO=<skills-zig-path> zig build build-cron -Doptimize=ReleaseFast" >&2 fi return 1 }
-
List automations: run_cron_tool list
-
Show one automation: run_cron_tool show --id <id>
-
Create an automation: run_cron_tool create --name "Weekly release notes" --prompt-file /path/to/prompt.md --rrule "RRULE:FREQ=WEEKLY;BYDAY=FR;BYHOUR=9;BYMINUTE=0"
-
Update an automation: run_cron_tool update --id <id> --rrule "RRULE:FREQ=DAILY;BYHOUR=9;BYMINUTE=0"
-
Enable or disable: run_cron_tool enable --id <id> or run_cron_tool disable --id <id>
-
Run immediately: run_cron_tool run-now --id <id>
-
Delete: run_cron_tool delete --id <id>
-
Run due automations once: run_cron_tool run-due
-
Run due automations dry-run: run_cron_tool run-due --dry-run
-
Install/start launchd scheduler (macOS): run_cron_tool scheduler install
-
Stop/remove launchd scheduler (macOS): run_cron_tool scheduler uninstall
-
Show scheduler status (macOS): run_cron_tool scheduler status
Runtime bootstrap policy mirrors seq /cas /lift : require the Zig binary, default to Homebrew install on macOS, and fallback to direct Zig install from skills-zig on non-macOS.
Subcommand --help prints top-level usage. For detailed options, use the matrix below.
Workflow
-
Choose working directories (cwds ). Default is current repo if omitted on create .
-
Write the automation prompt (use --prompt-file for multi-line prompts).
-
Provide an RFC5545 RRULE string.
-
Create or update with cron .
-
For unattended execution, install scheduler via cron scheduler install .
Headless Runner
-
cron run-due executes due automations by calling codex exec and updates:
-
automations.last_run_at
-
automations.next_run_at
-
automation_runs rows
-
cron run-due --dry-run is read-only:
-
no automation_runs rows are inserted/updated
-
no automations.last_run_at /next_run_at updates
-
no automation files or memory.md writes
-
--codex-bin accepts executable name or absolute path (default resolves $CODEX_BIN or codex in PATH ).
-
Locking is label-scoped and fail-closed (--lock-label , or env CRON_LAUNCHD_LABEL ).
-
--lock-label uses strict label validation: only [A-Za-z0-9._-] (no slashes/spaces).
-
run-due default batch limit is 10 automations per invocation (--limit overrides).
-
Scheduler commands are macOS-only and manage ~/Library/LaunchAgents/<label>.plist directly from Zig.
-
Launchd scheduler runs run-due with default DB path and default limit unless you invoke cron manually with overrides.
-
Logs: ~/Library/Logs/codex-automation-runner/out.log and ~/Library/Logs/codex-automation-runner/err.log .
Command Options (High Signal)
-
list : --status <ACTIVE|PAUSED> , --json
-
show : --id <id> or --name <name> , optional --json
-
create : --name , --prompt|--prompt-file , --rrule , optional --status , --cwd (repeatable), --cwds-json , --clear-cwds , --next-run-at
-
update : --id|--name , optional --new-name , --prompt|--prompt-file , --rrule , --status , --cwd (repeatable), --cwds-json , --clear-cwds , --next-run-at , --clear-next-run-at
-
enable|disable|run-now|delete : --id or --name
-
run-due : optional --id , --limit , --dry-run , --codex-bin , --lock-label ([A-Za-z0-9._-] only)
-
scheduler install : optional --label , --interval-seconds , --path , --codex-bin
-
scheduler uninstall|status : optional --label
-
Scheduler --label is strict: only [A-Za-z0-9._-] (no slashes/spaces).
Clarify When Ambiguous
Ask questions only when the request is ambiguous or when the user explicitly asks for guidance. Do not block otherwise.
Essential elements to confirm or infer:
-
Automation name.
-
Prompt content (single line or file path).
-
Schedule as an RFC5545 RRULE string (include RRULE: prefix).
-
Working directories (cwds ), default to current repo if not specified.
-
Status if explicitly requested; otherwise default to ACTIVE .
When ambiguous, ask for missing details. Examples:
-
If user says “daily”/“weekly” without time, ask for required time/day fields.
-
If user says “run it for this repo” without paths, confirm repo root as cwd .
Schedule (RRULE)
-
Accept only RFC5545 RRULE strings. Cron expressions are unsupported.
-
Rules are canonicalized to RRULE: -prefixed form.
-
Legacy non-prefixed stored values (FREQ=... ) are still accepted at run time for compatibility.
-
Validation is fail-closed.
-
BYHOUR /BYMINUTE are interpreted in UTC.
-
Supported frequencies:
-
HOURLY requires BYMINUTE
-
DAILY requires BYHOUR and BYMINUTE
-
WEEKLY requires BYDAY , BYHOUR , and BYMINUTE
Example rules:
-
Daily at 09:00: RRULE:FREQ=DAILY;BYHOUR=9;BYMINUTE=0
-
Weekly on Friday at 09:00: RRULE:FREQ=WEEKLY;BYDAY=FR;BYHOUR=9;BYMINUTE=0
-
Every 24 hours: RRULE:FREQ=HOURLY;INTERVAL=24;BYMINUTE=0
Task Examples
Daily standup summary
Name: Summarize yesterday's git activity
Prompt: Summarize yesterday's git activity for standup. Include notable commits, files touched, and any risks or follow-ups. Schedule: RRULE:FREQ=DAILY;BYHOUR=9;BYMINUTE=0
Weekly release notes
Name: Draft weekly release notes
Prompt: Draft weekly release notes from merged PRs. Include links when available and group by area. Schedule: RRULE:FREQ=WEEKLY;BYDAY=FR;BYHOUR=9;BYMINUTE=0
CI failure triage
Name: Summarize CI failures
Prompt: Summarize CI failures and flaky tests from the last CI window, group by root cause, and suggest minimal fixes. Schedule: RRULE:FREQ=DAILY;BYHOUR=8;BYMINUTE=30
Data Model Reference
See references/db.md for schema and field notes.