cron

SKILL.md

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

  1. Choose working directories (cwds). Default is current repo if omitted on create.
  2. Write the automation prompt (use --prompt-file for multi-line prompts).
  3. Provide an RFC5545 RRULE string.
  4. Create or update with cron.
  5. 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:

  1. Automation name.
  2. Prompt content (single line or file path).
  3. Schedule as an RFC5545 RRULE string (include RRULE: prefix).
  4. Working directories (cwds), default to current repo if not specified.
  5. 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.

Weekly Installs
20
GitHub Stars
43
First Seen
Feb 28, 2026
Installed on
opencode20
gemini-cli20
github-copilot20
codex20
kimi-cli20
amp20