2026-02-14 11:34:00 -07:00
# systab
A cron/at-like interface for systemd user timers. Create, manage, and monitor scheduled jobs without writing unit files by hand.
2026-02-15 00:58:11 -07:00
< table >
< tr >
< td width = "33%" > < img src = "demo/quickstart.gif" alt = "Quick start demo" > < / td >
< td width = "33%" > < img src = "demo/editmode.gif" alt = "Edit mode demo" > < / td >
< td width = "33%" > < img src = "demo/notifications.gif" alt = "Notifications demo" > < / td >
< / tr >
< tr >
< td align = "center" > < b > Quick start< / b > < / td >
< td align = "center" > < b > Edit mode< / b > < / td >
< td align = "center" > < b > Notifications< / b > < / td >
< / tr >
< / table >
2026-02-14 11:34:00 -07:00
## Install
Copy the `systab` script somewhere on your `$PATH` :
```bash
cp systab ~/.local/bin/
```
2026-02-14 14:43:06 -07:00
Requires `bash` , `systemctl` , and optionally `notify-send` (for `-i` ) and `sendmail` /`msmtp` (for `-m` ).
2026-02-14 11:34:00 -07:00
## Quick start
```bash
# Run a command every 5 minutes
systab -t "every 5 minutes" -c "curl -s https://example.com/health"
# Run a backup script every day at 2am
systab -t "every day at 2am" -f ~/backup.sh
# Run a one-time command in 30 minutes
systab -t "in 30 minutes" -c "echo reminder"
# Check status of all jobs
systab -S
# View logs
systab -L
```
## Time formats
systab accepts several time formats:
| Format | Example | Type |
|--------|---------|------|
| Natural recurring | `every 5 minutes` | Recurring |
| Natural recurring | `every 2 hours` | Recurring |
| Natural recurring | `every 30 seconds` | Recurring |
| Natural recurring | `every day at 2am` | Recurring |
| Natural recurring | `every monday at 9am` | Recurring |
| Natural recurring | `every month` | Recurring |
| Relative | `in 5 minutes` | One-time |
| Relative | `tomorrow` | One-time |
| Absolute | `2025-06-15 14:30` | One-time |
| Absolute | `next tuesday at noon` | One-time |
| Systemd keyword | `hourly` , `daily` , `weekly` , `monthly` | Recurring |
| Systemd OnCalendar | `*:0/15` (every 15 min) | Recurring |
| Systemd OnCalendar | `*-*-* 02:00:00` (daily at 2am) | Recurring |
| Systemd OnCalendar | `Mon *-*-* 09:00` (Mondays at 9am) | Recurring |
Relative and absolute formats are parsed by `date -d` . Systemd OnCalendar values are passed through directly.
## Usage
### Creating jobs
```bash
# Command string
systab -t "every 5 minutes" -c "echo hello"
# Script file
systab -t "every day at 2am" -f ~/backup.sh
# From stdin
echo "ls -la /tmp" | systab -t daily
2026-02-14 14:43:06 -07:00
# With desktop notification (success/failure with status icon)
2026-02-14 11:34:00 -07:00
systab -t "in 1 hour" -c "make build" -i
2026-02-14 14:43:06 -07:00
# With email notification (via sendmail)
2026-02-14 11:34:00 -07:00
systab -t "every day at 6am" -c "df -h" -m user@example .com
2026-02-14 16:35:52 -07:00
# Include last 10 lines of output in notification
2026-02-14 21:49:18 -07:00
systab -t "every day at 6am" -c "df -h" -i -o
2026-02-14 11:34:00 -07:00
```
### Managing jobs
```bash
# Edit all jobs in your $EDITOR (crontab-style)
2026-02-15 00:41:21 -07:00
systab -e
2026-02-14 11:34:00 -07:00
# Show status of all jobs
systab -S
2026-02-14 14:43:06 -07:00
# Show status of a specific job
systab -S a1b2c3
2026-02-14 11:34:00 -07:00
# View logs (all jobs)
systab -L
2026-02-14 14:43:06 -07:00
# View logs for a specific job
systab -L a1b2c3
2026-02-14 11:34:00 -07:00
# View logs (filtered)
systab -L error
2026-02-15 00:41:21 -07:00
# Disable a job
systab -D < id >
2026-02-14 11:34:00 -07:00
2026-02-15 00:41:21 -07:00
# Enable a disabled job
systab -E < id >
2026-02-14 11:34:00 -07:00
# Clean up completed one-time jobs
systab -C
```
### Edit mode
2026-02-15 00:41:21 -07:00
`systab -e` opens your editor with a pipe-delimited job list:
2026-02-14 11:34:00 -07:00
```
a1b2c3 | daily | /home/user/backup.sh
2026-02-14 14:43:06 -07:00
d4e5f6:i | *:0/15 | curl -s https://example.com
g7h8i9:e=user@host | weekly | ~/backup.sh
2026-02-15 00:41:21 -07:00
# aabbcc | hourly | echo "this job is disabled"
2026-02-14 11:34:00 -07:00
```
- Edit the schedule or command to update a job
- Delete a line to remove a job
- Add a line with `new` as the ID to create a job: `new | every 5 minutes | echo hello`
2026-02-15 00:41:21 -07:00
- Comment out a line (`#` ) to disable, uncomment to enable
2026-02-14 16:35:52 -07:00
- Append notification flags after the ID with `:` — `i` for desktop, `e=addr` for email, `o` for output (default 10 lines), `o=N` for custom count, comma-separated (e.g., `a1b2c3:i,o,e=user@host` )
2026-02-14 11:34:00 -07:00
### Job IDs
2026-02-15 00:41:21 -07:00
Each job gets a 6-character hex ID (e.g., `a1b2c3` ) displayed on creation and in status output. Use this ID with `-D` , `-E` , and `-L` .
2026-02-14 11:34:00 -07:00
## How it works
systab creates systemd `.service` and `.timer` unit file pairs in `~/.config/systemd/user/` . Each managed unit is tagged with a `# SYSTAB_MANAGED` marker comment. One-time jobs auto-unload after firing. Job output (stdout/stderr) is captured in the systemd journal and viewable via `systab -L` .
2026-02-14 14:43:06 -07:00
Notifications use `ExecStopPost` so they fire after the service completes regardless of success or failure. Desktop notifications show `dialog-information` or `dialog-error` icons based on `$SERVICE_RESULT` . Notification flags are persisted as `# SYSTAB_FLAGS=` comments in service files, so they survive across edit sessions.
2026-02-14 11:34:00 -07:00
## Options
```
Job Creation:
-t < time > Time specification (required for job creation)
-c < command > Command string to execute
-f < script > S c r i p t f i l e t o e x e c u t e ( r e a d s s t d i n i f n e i t h e r - c n o r - f )
2026-02-14 14:43:06 -07:00
-i Send desktop notification on completion (success/failure)
-m < email > Send email notification to address (via sendmail)
2026-02-14 21:49:18 -07:00
-o [lines] Include job output in notifications (default: 10 lines)
2026-02-14 11:34:00 -07:00
Management:
2026-02-15 00:41:21 -07:00
-D < id > Disable a job
-E < id > Enable a disabled job
-e Edit jobs in crontab-like format
2026-02-14 14:43:06 -07:00
-L [id] [filter] List job logs (optionally for a specific job and/or filtered)
-S [id] Show status of all managed jobs (or a specific job)
2026-02-14 11:34:00 -07:00
-C Clean up completed one-time jobs
-h Show help
```
2026-02-15 01:21:27 -07:00
## FAQ
**What's the difference between `-c` and `-f` ?**
`-f` validates that the file exists and is executable at creation time, catching typos and permission issues early. With `-c` , errors only surface when systemd runs the job later (visible via `systab -L` ). Under the hood, both produce the same `ExecStart` line.