timertab

module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Mar 7, 2026 License: MIT

README

timertab

Cron jobs done right — one YAML file, real systemd timers under the hood.

If you've ever wished crontab -e gave you systemd timers instead of 1970s cron, this is that tool. You write a simple YAML config, timertab turns it into proper .service and .timer units. No daemon, no lock-in — just plain systemd.

Why not just use crontab?

Systemd timers are better than cron in almost every way: structured logging through journald, resource controls, dependency ordering, per-user isolation. But managing them by hand means writing two unit files per job and juggling systemctl enable, daemon-reload, and cleanup yourself.

timertab takes care of all of that. You get the simplicity of crontab with the power of systemd timers.

Why not just write unit files?

You absolutely can — and timertab won't stop you. In fact, that's the point: the generated units are standard systemd, human-readable, and work without timertab installed. If you ever want to stop using this tool, run timertab eject <id> and your timer keeps running on its own.

Features

  • One YAML file — all your scheduled jobs in one place, version-control friendly.
  • Success and failure hooks — run a command when a job succeeds or fails (send a notification, dump logs, trigger another script).
  • Cron syntax you already know@hourly, @daily, or standard 5-field cron expressions.
  • Multiline scripts — these just work, run multiple commands without && abuse.
  • Multiple schedules per jobwhen accepts a list, so one job can fire at different times.
  • Zero lock-in — eject any job and it keeps running as a standalone systemd timer.
  • Per-user isolation — units are scoped to your UID; timertab never touches units it didn't create.
  • Raw systemd overrides when needed — set extra [Service] / [Timer] directives per job.
  • JSON Schema — get autocomplete and validation in editors that support it.
  • Safe reconcile — if your config is invalid, nothing gets written or pruned. No partial state.

Quick start

Install
go install github.com/ginden/timertab/cmd/timertab@latest

Or from a local clone:

make install
Create your first job
timertab -e

This opens your $EDITOR with the config file. Add a job:

$schema: "https://raw.githubusercontent.com/ginden/timertab/v1.0.0/schema/v1.json"
version: 1
instance_id: work
jobs:
  - name: clean temp files
    when: "@daily"
    run: "find /tmp -user $USER -mtime +7 -delete"

Save and close — timertab validates the config, generates the systemd units, and starts the timer. That's it.

A more complete example
$schema: "https://raw.githubusercontent.com/ginden/timertab/v1.0.0/schema/v1.json"
version: 1
jobs:
  - name: NPM cache verify
    when: "@hourly"
    run: "npm --global cache verify"
    env:
      NPM_CONFIG_PREFIX: "/home/user/.npm-global"
    on_success:
      command: "echo ok"
    on_failure:
      command: 'journalctl -u "$TIMERTAB_UNIT" -n 100 --no-pager'

  - name: backup documents
    when:
      - "0 9 * * *"
      - "0 18 * * *"
    run: "rsync -a ~/Documents /mnt/backup/"
    cwd: "/home/user"
    systemd:
      service:
        Restart: "on-failure"
        RestartSec: "30s"
      timer:
        AccuracySec: "1m"
    on_failure:
      command: 'notify-send "Backup failed"'

Usage

Command What it does
timertab edit (or timertab -e) Edit config, validate, and apply (generate and start timers)
timertab edit --no-apply (or timertab -e --no-apply) Edit and validate only, don't touch systemd
timertab edit --no-commit Apply without creating/updating the git history entry for that edit run
timertab list / timertab print-config (or timertab -l) Print current config
timertab status / timertab status --json Show last run, next trigger, and result for each job
timertab status <id> Show detailed runtime state, generated unit definitions, file locations, and diagnostic commands
timertab eject <id> Stop managing a job — its units stay and keep running
timertab enable <id> / timertab disable <id> Toggle one job on/off without removing it
timertab logs <id> Tail/query journald logs for one job
timertab diff Preview create/modify/delete reconcile operations
timertab import Convert crontab entries into timertab YAML
timertab validate --config <path> Validate a config file without applying
timertab print-path (or timertab --print-path) Show where the config file lives

Config file location:

  • --config <path> if provided
  • ${TIMERTAB_CONFIG_DIR}/timertab.yaml if TIMERTAB_CONFIG_DIR is set
  • otherwise ${XDG_CONFIG_HOME:-$HOME/.config}/timertab/timertab.yaml
Shell Completions

Generate completions with timertab completion <shell>.

bash

timertab completion bash > ~/.local/share/bash-completion/completions/timertab

zsh

timertab completion zsh > ~/.zfunc/_timertab

Then make sure ~/.zfunc is on your fpath.

fish

timertab completion fish > ~/.config/fish/completions/timertab.fish

Requirements

  • Linux with systemd ≥ 247
  • A running user session (systemctl --user must work)

If you need timers to fire while you're logged out:

loginctl enable-linger "$USER"

timertab will automatically detect this and print instructions if it's not set up.

How it works

When you run timertab edit (or timertab -e), here's what happens:

  1. Your editor opens the YAML config.
  2. On save, timertab validates the config against the schema and semantic rules.
  3. Missing job id fields are auto-generated and persisted back to the file.
  4. For each job, a .service and .timer unit is rendered.
  5. Stale units (from removed jobs) are stopped, disabled, and deleted.
  6. New/changed units are written, daemon-reload is called, and timers are started.

If validation fails at step 2, nothing else happens — no partial writes, no orphaned units.

Successful timertab edit apply runs also auto-commit the config file by default. If the config directory is not already inside a git work tree, timertab initializes one first, then stages and commits the config change. Disable that once with timertab edit --no-commit, or persistently in config:

git:
  auto_commit: false

Spec and schema

License

MIT © Michał Wadas

Directories

Path Synopsis
cmd
timertab command
internal
cli

Jump to

Keyboard shortcuts

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