# koku
A system-level cron daemon written in Rust. Japanese for "to mark/carve time" (刻).
Single binary that manages and runs scheduled jobs, with an integration point for kagaya to surface cron status and trigger one-off runs. CLI alias: `ku`.
## What it is
- A single binary (`koku`) — `ku daemon start` runs the daemon, all other subcommands talk to it via Unix socket
- CLI for managing jobs: status, one-off runs, pause/resume, log viewing
- A library crate others can embed if needed
## Architecture
- **Scheduler**: `croner` for cron expression parsing, custom scheduler loop on top of tokio
- **Daemon**: `ku daemon start` runs the scheduler in background (`ku daemon run` for foreground). Unix socket IPC (via muzan) for CLI ↔ daemon communication
- **Config**: TOML file defining jobs — name, cron expression, command, working dir, error policy
- **Logging**: Per-job structured log output (job name, exit code in every line)
- **Process execution**: Spawn jobs as child processes, capture stdout/stderr, track exit codes
## Config format
```toml
[[job]]
name = "backup"
cron = "0 2 * * *"
command = "bash backup.sh"
dir = "/home/user/scripts"
on_error = "backoff" # continue | backoff | stop (default: continue)
overlap = false # allow concurrent runs (default: false)
timeout = "30m" # kill job after duration (optional)
[[job]]
name = "cleanup"
cron = "*/15 * * * *"
command = "python3 cleanup.py"
```
### on_error policy (from Jobber's model)
- `continue` — ignore failures, keep scheduling (default)
- `backoff` — exponential backoff on failure, resume normal schedule on success
- `stop` — disable the job after repeated failures. Requires manual `ku resume` to re-enable
## Job states
```
idle waiting for next scheduled run
running currently executing
paused manually paused via `koku pause`
failing last run errored, will retry with backoff (on_error = backoff)
stopped disabled after repeated failures (on_error = stop). manual resume required
```
## CLI
```
ku init # scaffold ~/.config/koku/config.toml with examples
ku check # validate config, preview next-run times
ku daemon start # start daemon in background
ku daemon stop # stop daemon gracefully
ku daemon status # show daemon pid/uptime
ku status # table of all jobs with state/timing
ku status --json # machine-readable
ku run <name> # trigger one-off run
ku pause <name> # pause a job without editing config
ku resume <name> # resume a paused/stopped job
ku reload # reload config without restarting
```
### Status output
```
NAME STATE LAST RUN EXIT NEXT RUN
backup idle 2026-02-18 02:00:00 0 2026-02-19 02:00:00
cleanup running 2026-02-18 14:15:00 — —
sync failing 2026-02-18 14:00:00 1 2026-02-18 14:30:00
deploy paused 2026-02-17 18:00:00 0 —
```
## Kagaya integration
kagaya connects to koku's Unix socket to:
- Display cron job status in the process supervisor UI
- Trigger one-off runs from within kagaya
## Crates
- `muzan` — daemon lifecycle (Unix socket IPC, PID management, auto-start). Path dep: `~/dev/muzan`
- `tokio` — async runtime
- `croner` — cron expression parsing (lightweight, no scheduler opinions)
- `serde` + `toml` — config parsing
- `clap` — CLI
- `tracing` — structured logging (with job name, exit code fields)
- `comfy-table` — status table output
## Design influences
- **Jobber** (Go, unmaintained) — error handling model (continue/backoff/stop), error vs failure distinction, `test`/`pause`/`resume` commands, `init` scaffolding
- **Supercronic** (Go) — structured log fields per job (iteration, schedule, command), overlap detection with warnings, `-test` flag for config validation
- **Cronitor CLI** (Go) — `--json` flag on every command, `pause --hours` timed pause, progressive disclosure in output
- **Healthchecks.io** (Python) — clean state machine (idle/running/late/down), grace period concept
- **Cronie** (C) — `cronnext` for previewing schedules (→ `koku check`)
No Rust CLI cron manager exists. koku fills that gap.
## Future (post-v1)
- `ku log <name>` — per-job log viewing (requires per-job log files)
- Notification hooks (`on_failure` command per job, webhook support)
- Timed pause (`ku pause <name> --hours 24`)
- Random schedule jitter (Jobber's `R`, Cronie's `~`)
- Env vars per job in config
Web dashboard is provided by kagaya (`ky serve`), which connects to koku's Unix socket for cron status, one-off runs, and pause/resume.
## Naming
- Crate: `koku`
- Binaries: `koku` + `ku` (alias)
- Daemon: `ku daemon start` / `ku daemon run`
- Named after 刻 (koku) — Japanese for "to carve/mark time"