cronkit

module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 2, 2026 License: Apache-2.0

README

Cronkit

Make cron human again.

Cronkit is a command-line tool that makes cron jobs human-readable, auditable, and visual. It converts confusing cron syntax into plain English, generates upcoming run schedules, provides ASCII timeline visualizations, and validates crontabs with severity levels and diagnostic codes.

License Go Version codecov

Cronkit demo

Why Cronkit?

Cron syntax is hostile. You write 0 2 * * * and three months later you're staring at it wondering what it does. You inherit a crontab with sixty lines and no comments. You miss the difference between * * * * 1 (every Monday) and 0 0 1 * 1 (midnight on the 1st of the month and every Monday — because cron ORs day-of-month and day-of-week when both are set), and you find out at 3 AM on the wrong day.

Cronkit reads cron back to you in plain English, shows you when it'll actually run, and catches the dumb mistakes — DOM/DOW conflicts, missing absolute paths, missing output redirects, runaway frequencies — before they turn into a pager incident. It also finds schedules you didn't know to look for: scan walks a whole repository — crontabs, Kubernetes CronJobs, GitHub Actions workflows, Argo CronWorkflows — instead of asking you to point it at one crontab at a time. Pipe that discovery straight into an audit with cronkit scan . --json | cronkit check --inventory -: every schedule-consuming command reads an inventory back the same way, so a whole repository gets the same linting, timelines, statistics, and budget analysis a single crontab always had.

It runs offline, emits JSON for your pipelines, and never executes or modifies your crontabs. It's safe to drop into a pre-commit hook on day one.

  • Works offline - No network, no external service. Drop it into air-gapped boxes and CI runners without a second thought.
  • Built for CI/CD - Machine-readable JSON, deterministic exit codes, and a --fail-on severity gate that slots straight into pre-commit hooks and PR checks.
  • Visual timelines - ASCII timelines show schedule density and overlapping jobs at a glance, so you catch contention before it bites.
  • Real auditing - Severity-coded diagnostics, frequency analysis, command-hygiene checks, and concurrency-budget analysis — not just humanization.

Features

  • Explain - Convert cron expressions to plain English
  • Next - Show the next N scheduled run times
  • List - Parse and summarize crontab jobs from files or user crontabs
  • Scan - Discover cron schedules across a whole repository: crontabs, Kubernetes CronJobs, GitHub Actions workflows, and Argo CronWorkflows. Feed the result back into check, list, stats, budget, or timeline with --inventory to audit everything at once
  • Timeline - Visualize job schedules with ASCII timelines showing density and overlaps
  • Check - Validate crontab syntax with severity levels and diagnostic codes, including advanced linting (frequency analysis, command hygiene, overlap detection)
  • Doc - Generate comprehensive documentation (Markdown, HTML, JSON) from crontabs with optional sections
  • Stats - Calculate fleet statistics including run frequency metrics, collision analysis, and hour distribution
  • Diff - Compare crontabs semantically to see what actually changed (jobs added/removed/modified)
  • Budget - Analyze concurrency budgets to prevent resource exhaustion from too many simultaneous jobs
  • JSON Output - Machine-readable output for all commands via --json flag
  • Read-Only - Safe by design; never executes or modifies crontabs

How it compares

  • crontab.guru — Excellent web-based humanizer. Cronkit covers the same humanization in a CLI that works offline, and adds validation, timeline rendering, audit linting, diff, stats, and budget analysis.
  • cronstrue — JavaScript library for humanizing cron. Library-shaped, not a CLI; humanization only.
  • croniter — Python library for computing next runs. Library, not a CLI.
  • cronie / vixie-cron — The cron daemon itself. Different scope; Cronkit is a read-only auditing tool that complements whatever daemon you're running.

Cronkit's distinguishing position: a single static binary, offline, with machine-readable JSON output and severity-coded diagnostics, designed to live in pre-commit hooks and CI pipelines.

Installation

Homebrew (macOS/Linux)
brew tap hzerrad/cronkit
brew install --cask cronkit
Direct Binary Download

Download the pre-built binary for your platform from GitHub Releases:

# Linux (amd64)
wget https://github.com/hzerrad/cronkit/releases/latest/download/cronkit_linux_amd64.tar.gz
tar -xzf cronkit_linux_amd64.tar.gz
sudo mv cronkit /usr/local/bin/

# macOS (Apple Silicon)
wget https://github.com/hzerrad/cronkit/releases/latest/download/cronkit_darwin_arm64.tar.gz
tar -xzf cronkit_darwin_arm64.tar.gz
sudo mv cronkit /usr/local/bin/

# macOS (Intel)
wget https://github.com/hzerrad/cronkit/releases/latest/download/cronkit_darwin_amd64.tar.gz
tar -xzf cronkit_darwin_amd64.tar.gz
sudo mv cronkit /usr/local/bin/
Package Managers
APT (Debian/Ubuntu)

Add the repository once, then install and upgrade with apt like any other package:

echo "deb [trusted=yes] https://apt.fury.io/hzerrad-dev/ /" | sudo tee /etc/apt/sources.list.d/cronkit.list
sudo apt update
sudo apt install cronkit
Or install a standalone .deb without adding the repo
VERSION=0.1.1

# amd64
wget https://github.com/hzerrad/cronkit/releases/download/v${VERSION}/cronkit_${VERSION}_amd64.deb
sudo dpkg -i cronkit_${VERSION}_amd64.deb && sudo apt-get install -f

# arm64
wget https://github.com/hzerrad/cronkit/releases/download/v${VERSION}/cronkit_${VERSION}_arm64.deb
sudo dpkg -i cronkit_${VERSION}_arm64.deb && sudo apt-get install -f
DNF/YUM (Fedora/RHEL/CentOS)

Add the repository once, then install and upgrade with dnf like any other package:

sudo tee /etc/yum.repos.d/cronkit.repo >/dev/null <<'EOF'
[cronkit]
name=Cronkit
baseurl=https://yum.fury.io/hzerrad-dev/
enabled=1
gpgcheck=0
EOF
sudo dnf install cronkit
Or install a standalone .rpm without adding the repo
VERSION=0.1.1

# x86_64
sudo dnf install https://github.com/hzerrad/cronkit/releases/download/v${VERSION}/cronkit-${VERSION}-1.x86_64.rpm

# aarch64
sudo dnf install https://github.com/hzerrad/cronkit/releases/download/v${VERSION}/cronkit-${VERSION}-1.aarch64.rpm
Pacman/AUR (Arch Linux)

Install from the Arch User Repository (AUR) using an AUR helper:

# Using yay
yay -S cronkit-bin

# Using paru
paru -S cronkit-bin

# Or manually
git clone https://aur.archlinux.org/cronkit-bin.git
cd cronkit-bin
makepkg -si
Go Install

Install directly from source using Go:

go install github.com/hzerrad/cronkit/cmd/cronkit@latest

Note: This requires Go 1.25.2 or higher to be installed.

Build from Source

Clone the repository and build:

git clone https://github.com/hzerrad/cronkit.git
cd cronkit
make build
# Binary will be in ./bin/cronkit

# Or install directly
make install
Verify Installation

After installation, verify it works:

cronkit version

You should see the version information printed.

Quick Start

Explain a Cron Expression
$ cronkit explain "*/15 2-5 * * 1-5"
Runs every 15 minutes between 02:00–05:59 on weekdays (Mon–Fri).
Show Next Run Times
$ cronkit next "0 9 * * *" --count 5
Next 5 runs for "0 9 * * *" (At 09:00 daily):

1. 2025-12-29 09:00:00 UTC
2. 2025-12-30 09:00:00 UTC
3. 2025-12-31 09:00:00 UTC
4. 2026-01-01 09:00:00 UTC
5. 2026-01-02 09:00:00 UTC

# With timezone support
$ cronkit next "0 9 * * *" --timezone America/New_York --count 3
Next 3 runs for "0 9 * * *" (At 09:00 daily):

1. 2025-12-29 09:00:00 EST
2. 2025-12-30 09:00:00 EST
3. 2025-12-31 09:00:00 EST
List Crontab Jobs
$ cronkit list --file /etc/crontab
LINE  EXPRESSION        DESCRIPTION                          COMMAND
────  ────────────────  ───────────────────────────────────  ────────────────────────
1     0 2 * * *         At 02:00 daily                       /usr/bin/backup.sh
2     */15 * * * *      Every 15 minutes                     /usr/bin/check-disk.sh

# Read from stdin
$ cat /etc/crontab | cronkit list
# or
$ cronkit list --stdin < /etc/crontab
Visualize Timeline
$ cronkit timeline "*/15 * * * *" --view day
cronkit timeline — 2025-01-15 · day · UTC

Every 15 minutes┤╷┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃╷┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃╷├ */15 * * * *
                └┬───────────┬───────────┬───────────┬───────────┬┘
                00:00      06:00       12:00       18:00      23:59

1 job · 95 runs · no conflicts

Each job gets its own lane against a shared time axis; a conflicts lane appears when runs collide (add --show-overlaps for the time-by-time breakdown). Non-interactive output (piped, redirected, or CI) is plain (uncolored) Unicode with no color by default — use --color always or --ascii to force either behavior.

Validate Crontab
$ cronkit check --file /etc/crontab
✓ All valid (2 jobs)

$ cronkit check "0 0 1 * 1" --verbose
⚠ Found 1 warning(s)
  Total jobs: 1
  Valid: 1
  Invalid: 0

⚠ WARNING: Both day-of-month and day-of-week specified (runs if either condition is met) [CRON-001]
  Expression: 0 0 1 * 1
  Hint: Consider using only day-of-month OR day-of-week, not both. Cron uses OR logic (runs if either condition is met).

# Group issues by severity
$ cronkit check --file jobs.cron --group-by severity --verbose
━━━ Error Issues (2 issue(s)) ━━━
  ...

━━━ Warning Issues (1 issue(s)) ━━━
  ...

# Use in CI/CD with fail-on
$ cronkit check --file jobs.cron --fail-on warn --verbose
# Exits with code 2 if warnings are found

$ cronkit check "60 0 * * *"
✗ Found 1 issue(s)
  Total jobs: 1
  Valid: 0
  Invalid: 1

✗ ERROR: Invalid cron expression: expected 5 fields [CRON-003]
  Expression: 60 0 * * *
  Hint: Fix the syntax error in the cron expression. Ensure all 5 fields are present and valid.

Commands

Cronkit provides ten commands for working with cron expressions and crontabs:

  • explain — Convert a cron expression to plain English
  • next — Show the next N scheduled run times
  • list — Parse and summarize crontab jobs
  • scan — Discover cron schedules across a repository
  • timeline — ASCII timeline visualization of schedules
  • check — Validate syntax and lint for common issues
  • doc — Generate documentation from crontabs (Markdown, HTML, JSON)
  • stats — Frequency, collision, and distribution statistics
  • diff — Semantic diff between two crontabs
  • budget — Concurrency budget analysis

See docs/commands.md for the complete reference with all flags, examples, and exit codes.

Supported Cron Dialect

  • Standard 5-field Vixie cron: minute hour dom month dow
  • Aliases: @hourly, @daily, @weekly, @monthly, @yearly
  • Case-insensitive day/month names: MON-SUN, JAN-DEC
  • Ranges: 1-5, MON-FRI
  • Steps: */15, 0-23/2
  • Lists: 1,3,5, MON,WED,FRI

JSON Output

All commands support --json flag for machine-readable output. The JSON schema is stable and documented for automation and CI/CD integration.

Example - Explain:

$ cronkit explain "*/15 * * * *" --json
{
  "expression": "*/15 * * * *",
  "description": "Every 15 minutes",
  "locale": "en"
}

Example - Next (with timezone):

$ cronkit next "@daily" --timezone UTC --json -c 2
{
  "expression": "@daily",
  "description": "At midnight every day",
  "timezone": "UTC",
  "locale": "en",
  "nextRuns": [
    {
      "number": 1,
      "timestamp": "2025-12-29T00:00:00Z",
      "relative": "in 6 hours"
    },
    {
      "number": 2,
      "timestamp": "2025-12-30T00:00:00Z",
      "relative": "in 1 day"
    }
  ]
}

Example - Check (with severity and diagnostic codes):

$ cronkit check "0 0 1 * 1" --json --verbose
{
  "valid": true,
  "totalJobs": 1,
  "validJobs": 1,
  "invalidJobs": 0,
  "locale": "en",
  "issues": [
    {
      "severity": "warn",
      "code": "CRON-001",
      "lineNumber": 0,
      "expression": "0 0 1 * 1",
      "message": "Both day-of-month and day-of-week specified (runs if either condition is met)",
      "hint": "Consider using only day-of-month OR day-of-week, not both. Cron uses OR logic (runs if either condition is met).",
      "type": "warning"
    }
  ]
}

Example - List (with stdin):

$ echo "0 2 * * * /usr/bin/backup.sh" | cronkit list --json
{
  "jobs": [
    {
      "lineNumber": 1,
      "expression": "0 2 * * *",
      "command": "/usr/bin/backup.sh",
      "description": "At 02:00 daily"
    }
  ],
  "locale": "en"
}

Safety

Cronkit is read-only by design. It never executes or modifies crontabs. It's safe to use on production systems for auditing and documentation purposes.

Requirements

  • Go: 1.25.2 or higher (for building from source)
  • Platform: Linux, macOS, Windows (single static binary)

Development

Prerequisites
  • Go 1.25.2 or higher
  • Make
  • golangci-lint (recommended, for linting)
Building
make build          # Build binary (./bin/cronkit)
make build-all      # Cross-platform builds
make install        # Install to GOPATH/bin
Testing

This project follows Test-Driven Development (TDD) and Behavior-Driven Development (BDD) practices with 90%+ test coverage.

make test           # All tests (unit + integration + E2E)
make test-unit      # Unit tests only
make test-integration  # Integration tests
make test-e2e       # E2E tests
make test-coverage  # Generate coverage report
make benchmark      # Run performance benchmarks

Documentation:

Code Quality
make fmt            # Format code
make vet            # Run go vet
make lint           # Run golangci-lint
make setup-hooks    # Install pre-commit hooks
Project Structure
cronkit/
├── cmd/cronkit/          # CLI entry point
├── internal/            # Private application code
│   ├── cmd/            # Command implementations
│   ├── cronx/          # Cron parser abstraction
│   ├── human/          # Humanization templates
│   ├── render/         # Timeline renderer
│   ├── crontab/        # Crontab reader
│   └── check/          # Validation logic
├── test/               # Integration and E2E tests
│   ├── integration/    # Integration tests (Ginkgo)
│   └── e2e/           # E2E tests (Ginkgo)
├── testdata/          # Test fixtures
└── docs/              # Documentation

Contributing

See CONTRIBUTING.md for detailed guidelines.

Documentation

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

Author

hzerrad

Acknowledgments


Made with ❤️ for developers who work with cron jobs

Directories

Path Synopsis
cmd
cronkit command
internal
cmd
discover
Package discover locates the boundaries a discovery walk operates within.
Package discover locates the boundaries a discovery walk operates within.
doc
inventory
Package inventory holds the data model for a discovered cron schedule and its JSON envelope.
Package inventory holds the data model for a discovered cron schedule and its JSON envelope.
source
Package source discovers schedules inside files, independent of the file's format.
Package source discovers schedules inside files, independent of the file's format.
timeutil
Package timeutil provides time helpers shared by the schedule analyzers.
Package timeutil provides time helpers shared by the schedule analyzers.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL