{"slug": "show-hn-turnus-find-cron-launchd-and-systemd-jobs-that-won-t-run-and-why", "title": "Show HN: Turnus – find cron, launchd and systemd jobs that won't run, and why", "summary": "Developer Sanif Himani released Turnus, a terminal UI that lists cron jobs, launchd agents and systemd timers alongside tasks scheduled in Claude Desktop, the ChatGPT desktop app (Codex automations) and the Hermes agent, and flags jobs that are broken. Turnus runs 14 checks on cron, launchd and systemd jobs — including last-run failures, missing programs, unloaded plists, schedules that never match a real date, and jobs scheduled between 1 and 3 a.m. when daylight saving can skip them — plus 5 checks on AI-agent tasks, such as whether the app is closed or the task runs only while its app or service is running. It is read-only, installs via Homebrew or Go 1.26 or later, and its `turnus ls --check` mode exits with status 1 when any job is failing so it can run as a CI or cron watchdog.", "body_md": "turnus is a terminal UI for the cron jobs, launchd agents and systemd timers on your machine.\n\nIt also reads the tasks you schedule in Claude Desktop, the ChatGPT desktop app (Codex automations) and the Hermes agent. It lists every job in one place and flags the ones that are broken. It tells you when a job's last run failed or crashed, when its program no longer exists, when its plist never loaded, and when its schedule can never run. For each problem, turnus explains how to fix it, usually with a command you can copy.\n\nturnus only reads your jobs. It never changes them, and it doesn't run in the background.\n\nInstall turnus with Homebrew.\n\n```\nbrew install sanifhimani/tap/turnus\n```\n\nIf brew says the cask is invalid, run `brew update` and try again. turnus needs\na current version of Homebrew.\n\nYou can also install it with Go 1.26 or later.\n\n```\ngo install github.com/sanifhimani/turnus/cmd/turnus@latest\n```\n\nRun `turnus` to browse your jobs, or `turnus ls` to print them as a table.\n\n```\nturnus             # open the browser\nturnus ls          # print the table\nturnus ls --json   # print JSON\nturnus ls --check  # exit with status 1 if any job is failing\nturnus -a          # include jobs that ship with the OS\n```\n\n`--check` lets you run turnus from CI or from cron as a watchdog. turnus exits\nwith status 0 when no job is failing, 1 when at least one is, and 2 when it hits\nan error. Warnings don't change the exit status.\n\n`--json` prints an object with a `version` number, the `jobs`, and any `errors`\nfrom schedulers turnus couldn't read. The version changes only when a field is\nremoved or changes meaning.\n\nThe browser uses these keys.\n\n| Key | Action | \n|---|---|\n| `j`` k` or arrows | Move | \n| `/` | Filter | \n| `enter` | Show the job's details | \n| `e` | Edit the job's file, or run `crontab -e` for your crontab | \n| `l` | Open the job's log, or `journalctl` for a systemd timer | \n| `c` | Copy the fix | \n| `a` | Show or hide the OS's own jobs | \n| `q` | Quit | \n\nturnus runs these checks on every cron, launchd and systemd job.\n\n| Check | cron | launchd | systemd | \n|---|---|---|---|\n| The last run failed or crashed |  | ✓ | ✓ | \n| The program is missing or not executable | ✓ | ✓ | ✓ | \n| The log folder is missing, so the job can't start | ✓ | ✓ |  | \n| The job isn't loaded or the timer isn't started |  | ✓ | ✓ | \n| The timer starts a service that doesn't exist |  |  | ✓ | \n| The crontab line or the plist is invalid | ✓ | ✓ |  | \n| turnus can't read the file, usually for lack of permission | ✓ | ✓ |  | \n| The schedule never matches a real date | ✓ | ✓ | ✓ | \n| The command has an unescaped `%` , which cron treats as the end of the command | ✓ |  |  | \n| `run-parts` skips the script because of the characters in its name | Debian and Ubuntu |  |  | \n| The job runs between 1 and 3 a.m., when daylight saving can skip it | ✓ | ✓ | ✓ | \n| The scheduler skips runs missed while the machine sleeps or is off | macOS | `StartInterval` | Without `Persistent=true` | \n| The job reads `~/Documents` , which cron can't do without Full Disk Access | macOS |  |  | \n| The job's output goes nowhere | ✓ |  |  | \n\nturnus runs these checks on the tasks that AI agents schedule.\n\n| Check | Claude Desktop | ChatGPT desktop app | Hermes | \n|---|---|---|---|\n| The app skipped the last run, with the reason it gives | ✓ |  |  | \n| The last run failed |  |  | ✓ | \n| The schedule is invalid | ✓ |  | ✓ | \n| The task runs only while its app or service is running | ✓ | ✓ | ✓ | \n| The app is closed, so the task won't run | ✓ |  |  | \n\nlaunchd returns exit code 78 for both a missing program and a missing log folder, and systemd returns 203 for any program it can't start. turnus checks the files to tell you which problem caused the failure.\n\nturnus reads cron jobs from your crontab, `/etc/crontab`, `/etc/cron.d` and the\n`/etc/cron.{hourly,daily,weekly,monthly}` folders. It reads launchd jobs from\nthe LaunchAgents and LaunchDaemons folders and gets their status from\n`launchctl print`. It reads systemd timers for both the system and your user\nand gets their status from `systemctl show`.\n\nturnus reads Claude Desktop's scheduled tasks from its folder in\n`~/Library/Application Support/Claude`, the ChatGPT desktop app's scheduled\ntasks from `~/.codex/automations`, and Hermes jobs from\n`~/.hermes/cron/jobs.json`. Claude Desktop and ChatGPT don't document these\nfiles, so turnus reads them carefully and tells you when it finds a format it\ndoesn't know.\n\ncron keeps no history of past runs, so turnus can't tell you whether a cron job's last run succeeded.\n\nturnus runs on macOS and Linux.\n\nturnus is released under the [MIT License](https://github.com/sanifhimani/turnus/blob/main/LICENSE).", "url": "https://wpnews.pro/news/show-hn-turnus-find-cron-launchd-and-systemd-jobs-that-won-t-run-and-why", "canonical_source": "https://github.com/sanifhimani/turnus", "published_at": "2026-11-10 13:40:00+00:00", "updated_at": "2026-11-10 13:53:40.719314+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-products"], "entities": ["Turnus", "Sanif Himani", "Claude Desktop", "ChatGPT desktop app", "Codex", "Hermes", "Homebrew", "Go"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-turnus-find-cron-launchd-and-systemd-jobs-that-won-t-run-and-why", "markdown": "https://wpnews.pro/news/show-hn-turnus-find-cron-launchd-and-systemd-jobs-that-won-t-run-and-why.md", "text": "https://wpnews.pro/news/show-hn-turnus-find-cron-launchd-and-systemd-jobs-that-won-t-run-and-why.txt", "jsonld": "https://wpnews.pro/news/show-hn-turnus-find-cron-launchd-and-systemd-jobs-that-won-t-run-and-why.jsonld"}}