Skip to content

Install real Windows timers via schtasks - #1

Merged
debashisn94 merged 1 commit into
mainfrom
windows-timers
Sep 4, 2026
Merged

debashisn94 merged 1 commit into
mainfrom
windows-timers

Conversation

@debashisn94

Copy link
Copy Markdown
Contributor

What

holt schedule and a routine's --at did nothing useful on Windows. They saved the job to the store, then printed a cron line the OS cannot use, so holt schedule list showed a timer that was never going to fire.

Windows now gets a real Task Scheduler entry.

How

A .cmd wrapper is written to ~/.holt/tasks/<id>.cmd and registered with schtasks, mirroring how macOS gets a launchd plist.

The wrapper exists specifically so the command never has to survive schtasks /TR quoting. /TR takes a single string and mangles embedded quotes, which breaks the moment a task phrase or a path under Program Files contains a space. A batch file has none of that problem.

Entry generation stays pure (buildWindowsScript, buildSchtasksArgs, cmdQuote), which is what makes the Windows path testable from a Mac at all.

Also: deduplication

routine.ts had its own copies of installDarwin, installLinux, currentCrontab, writeCrontab, and both remove functions, copy-pasted from schedule.ts. Both now go through installForPlatform / removeForPlatform.

Routines get Windows support for free, and the two commands can no longer drift apart. Net 72 lines removed from routine.ts.

Testing

New scripts/scheduler.test.ts, wired into npm test. 14 checks covering cmd quoting rules, doubled-quote escaping, CRLF endings, cd /d, notify ordering after the errorlevel guard, routine runArgs, and /ST zero-padding.

Verified by hand on macOS that both round-trips still work after the refactor: schedule add / remove and routine add --at / remove each create and then fully clean up their plist and launchd registration.

Not verified on real Windows hardware. The pure builders are pinned by tests, but nobody has watched schtasks accept the argv on an actual machine.

Docs

README, docs/INSTALL.md, and the audit skill no longer say Windows scheduling is unsupported. The remaining honest caveat, now documented: a scheduled run is skipped rather than caught up if the machine was asleep at that time.

holt schedule and a routine's --at previously did nothing useful on
Windows: they saved the job, then printed a cron line the OS cannot use.

Windows now gets a .cmd wrapper in ~/.holt/tasks/ registered with
schtasks, mirroring how macOS gets a launchd plist. The wrapper exists so
the command never has to survive schtasks /TR quoting, which mangles
embedded quotes and breaks on any task phrase or path containing a space.

Entry generation stays pure (buildWindowsScript, buildSchtasksArgs), so
the Windows path is testable from a Mac. 14 checks cover the cmd quoting
rules, CRLF endings, notify ordering, and /ST zero-padding.

Also deduplicates the launchd and cron install/remove logic, which
routine.ts had copied from schedule.ts, behind installForPlatform and
removeForPlatform. Routines therefore get Windows support for free, and
the two commands can no longer drift apart.
@debashisn94
debashisn94 merged commit 89951cf into main Sep 4, 2026
2 checks passed
@debashisn94
debashisn94 deleted the windows-timers branch September 4, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant