repeat

module
v0.0.0-...-a756680 Latest Latest
Warning

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

Go to latest
Published: Sep 3, 2026 License: MIT

README

repeat

A cron and one-shot job scheduler.

ci coverage

It does two things:

  • recurring (cron-style) jobs
  • one-shot jobs at a wall-clock time

Both run inside its own daemon, so behaviour is the same on macOS and Linux. The system cron isn't involved.

State lives in a single SQLite file under the platform's data directory. Captured output for the last 100 runs per job is retained for 100 days.

Why

I've been using LLM agents to schedule both one-off and recurring jobs. The agents I use keep their job ticker inside their own process and there's little visibility into it. For some tasks that's adequate, but for others I'd like to see all the scheduled jobs in one place.

The system cron works, but it takes some shell-fu to check state and tail the output. One-off scheduling is also inconsistent across platforms: on macOS, the at daemon is usually off by default. So I wanted a small, self-documenting CLI that an LLM can drive and that behaves the same on macOS and Linux.

Quickstart

Install

macOS:

brew tap mahibulhaque/repeat https://github.com/mahibulhaque/repeat
# Newer Homebrew requires trusting third-party taps.
brew trust mahibulhaque/repeat
brew install --cask repeat

Linux:

curl -fsSL https://raw.githubusercontent.com/mahibulhaque/repeat/main/install.sh | sh

From source:

go install github.com/mahibulhaque/repeat/cmd/repeat@latest

On systems without launchd or systemd (Alpine, WSL, containers), skip repeat install and run the daemon in a loop:

mkdir -p ~/.local/share/repeat
nohup sh -c 'until repeat daemon; do sleep 1; done' >> ~/.local/share/repeat/repeat.log 2>&1 &

The loop restarts the daemon after a crash. repeat stop stops the daemon and ends the loop.

A restart loses nothing. The schedule lives in SQLite. A missed one-shot fires on the next start. A run that was killed mid-run is recorded as interrupted. It is not retried, because the command may have finished right before the crash.

To start the loop at boot, put the same line in your system's boot hook, for example /etc/local.d, a runit service, or wsl.conf.

Use

Register the daemon with launchd (macOS) or systemd --user (Linux) so it restarts across logins and crashes:

# Register the supervisor unit once.
repeat install

Add recurring jobs. Everything after -- is the command repeat will run:

# Record weekday disk space.
repeat add --cron '0 9 * * 1-5' --name disk-space -- sh -c 'date; df -h "$HOME"'

# Check a website every 15 minutes.
repeat add --cron '*/15 * * * *' --name homepage-check -- curl -fsS https://example.com

Add one-shot jobs:

# Run after a relative delay.
repeat add --at '+30m' --name stretch -- sh -c 'printf "stand up and stretch\n"'

# Run at a wall-clock time.
repeat add --at 'tomorrow 9am' --name morning-note -- sh -c 'printf "review calendar\n"'

List and inspect:

# List jobs in a compact table.
repeat ls

# Emit JSON for scripts.
repeat ls --json

# Show one job's schedule and state.
repeat show disk-space

# Read captured output after a run has completed.
repeat logs disk-space --lines 50

# Stream future completed runs.
repeat logs disk-space --follow

# Check daemon state, supervisor state, and job counts.
repeat status

Control the lifecycle:

# Pause a job without deleting it.
repeat disable disk-space

# Re-enable it.
repeat enable disk-space

# Delete a job and its run history.
repeat rm stretch

# Ask the daemon to exit.
repeat stop

# Purge done one-shots and disabled jobs.
repeat prune

# Remove the supervisor unit.
repeat uninstall

Development

Requires Go 1.27 or newer.

make build
make test
make vet
make lint
make tidy
make clean

make e2e drives the real binary end to end. The architecture is described in docs/arch.md and the test layout in docs/testing.md.

Releases

Tagged v* pushes trigger a goreleaser build via .github/workflows/release.yml.

Directories

Path Synopsis
cmd
repeat command
internal
daemon
Package daemon contains daemon-lifecycle helpers.
Package daemon contains daemon-lifecycle helpers.
scheduler
Package scheduler is the scheduler loop.
Package scheduler is the scheduler loop.
store
Package store persists jobs and run history in SQLite.
Package store persists jobs and run history in SQLite.

Jump to

Keyboard shortcuts

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