Release Notes
goodmorning-claude 1.2.0 - 11 Jul 2026
Changes
- New default schedule —
installwith no--timenow fires at 07:05, 12:10 and 17:15 (previously 07:05, 12:05 and 17:05). The pings are now spaced 5h05m apart rather than exactly 5 hours, so each one lands just after the previous usage window has closed instead of racing its boundary.
Existing installs are unaffected until you re-run install.
Fixes
Three ways the schedule could silently stop firing while status still reported it as
healthy:
statusnow asks launchd whether the agent is really loaded, rather than inferring it from the plist file being present. An agent launchd has not loaded — booted out by hand, or left behind by a failed install — will never fire, andstatusused to report it as a working schedule. It now warns and exits1.- A failed
installno longer leaves a plist behind. Iflaunchctl bootstrapfails, the plist written moments earlier is removed, so a plist on disk always means a schedule launchd has accepted. -
installrefuses to run from an ephemeral location. Auvxinvocation's executable lives in uv's cache, whichuv cache prunecan delete; because the plist bakes in an absolute path, scheduling fromuvxproduced a schedule that worked right up until the cache was cleaned.installnow detects this (and temp directories) and tells you to install persistently first. The previously documenteduvx goodmorning-claude installis no longer supported — useuv tool install goodmorning-claude. -
The pinned
claudepath is no longer resolved through its symlink.claudeis installed as a stable symlink into a versioned directory (~/.local/bin/claude -> .../versions/2.1.110) which Claude Code retargets on every self-update.installused to pin the resolved target, which froze the schedule on whichever version happened to be current — and broke it outright once that version was pruned. The symlink is pinned instead, andrunfalls back to aPATHlookup if the pin has gone stale, so plists written by older versions repair themselves. statusnow checks that the paths in the plist still exist. launchd registers a job by absolute path and only discovers the path is dead when it tries to spawn it, so a schedule whose executable was deleted — byuv tool upgrade, a rebuilt venv, a moved install — still reported as loaded and healthy while failing silently at every fire.statusnow reports that as fatal, and a stale Claude pin as a note.
Also:
uninstallnow boots the agent out unconditionally, even when no plist is on disk. It could otherwise leave a loaded agent running with no way to stop it.- The launchd log is trimmed.
runrolls~/Library/Logs/goodmorning-claude.logover to a single.1sibling once it passes 1 MB; nothing rotated it before. --licenseis parsed by argparse rather than matched by scanningsys.argv, so an argument that merely looks like the flag can no longer trigger it.statusno longer echoes out-of-range fire times back from a hand-edited plist.
goodmorning-claude 1.1.0 - 17 Jun 2026
Features
- Multiple daily fire times —
install --timenow accepts more than oneHH:MMvalue (space-separated), writing aStartCalendarIntervalarray to the plist. Times are sorted and de-duplicated. - New default schedule —
installwith no--timenow schedules three pings at 07:05, 12:05 and 17:05 (previously a single 07:05 ping), spaced ~5 hours apart so each opens a fresh usage window that carries through to the next. statusnow lists every configured fire time.
Plists written by 1.0.x (a single StartCalendarInterval dict) are still read correctly.
goodmorning-claude 1.0.1 — 30 May 2026
Moved to new GitHub location: https://github.com/WaterJuice/goodmorning-claude
goodmorning-claude 1.0.0 — 23 Apr 2026
Initial release.
Features
- macOS-only — requires Darwin; the CLI refuses to run on any other platform
- Schedule a morning Claude ping —
install --time HH:MMsets up a daily run (default 07:05) - launchd integration — LaunchAgent plist installed in
~/Library/LaunchAgents/withStartCalendarInterval runfeedback — manual invocations print the binary being used and the elapsed time on success or failure--verbose/-vflag — accepted before or after the subcommand; emits detailed logs of every action and subprocess call to stderr- Resilient PATH handling — resolves
claudeat install time and bakes its directory into the plist so the schedule keeps firing even if the user's shell PATH depends on init scripts - Manual trigger —
runinvokes the morning ping on demand - Status command —
statusreports whether the schedule is installed and shows the configured time - Zero dependencies — stdlib only