Skip to content

Releases: homer6/frequent-cron

v0.3.2 - Jitter & Probabilistic Firing

13 Apr 03:25
7cb9c8b

Choose a tag to compare

Released: April 12, 2026

Patch release fixing a critical 100% CPU bug in daemon mode and adding optional jitter and probabilistic firing controls.

New Features

  • Jitter (#30) -- --jitter=<ms> adds random timing variance to each firing interval. Supports --jitter-distribution=<uniform|normal> (default: uniform). Useful for spreading load when many services fire at the same frequency.
  • Probabilistic firing (#30) -- --fire-probability=<0.0-1.0> skips a percentage of ticks at random. Default is 1.0 (fire every tick), preserving existing behavior.
  • Both features are optional, off by default, and persisted in the SQLite database with automatic schema migration for existing installs.
  • All four platform service definitions (systemd, launchd, rc.d, SCM) pass the new flags through.

Developer Experience

  • Claude Code skill for frequent-cron (#34) -- Added a Claude Code skill (.claude/skills/frequent-cron/) with command reference and service management instructions, enabling AI-assisted operation of the daemon.

Bug Fixes

  • Fix 100% CPU in daemon mode on macOS (#32) -- The Executor (which creates a boost::asio::io_context backed by kqueue on macOS) was constructed before daemonize() calls fork(). kqueue file descriptors are not inherited across fork, so the child process ended up with a stale kqueue fd, causing kevent() to return EBADF on every call -- turning the ASIO event loop into a busy spin instead of sleeping between timer ticks. Fix: moved Executor construction to after daemonize(). Affected all daemon-mode executions (both legacy --frequency= and run subcommand).
  • Fix service logs showing no output (#33, #31) -- frequent-cron logs <name> returned empty output for running services. The run subcommand was using system() which discards stdout/stderr. Fix: added --service-name to the run parser, wired a LogManager as the executor's OutputCallback so command output is captured via run_process(), and start now passes --service-name and --data-dir when launching the daemon.

Testing

  • 18 new unit tests: config (7), executor (7), database (4)
  • Total: 95 tests passing (77 existing + 18 new)

Upgrading

Drop-in replacement for v0.3.1. Existing databases are migrated automatically to add the new columns (jitter, jitter_distribution, fire_probability) with backward-compatible defaults.

v0.3.1 - Background Command Fix + Migration Guides

08 Apr 18:28
a53dc23

Choose a tag to compare

Released: April 8, 2026

Patch release fixing a regression where commands containing backgrounded subprocesses (command &) silently failed in legacy mode. Also adds migration guides and documents the release branch workflow.

Bug Fix

  • Fix background commands silently failing in legacy mode (#17) -- daemonize() was closing file descriptors 0-2 instead of redirecting them to /dev/null. This violates POSIX: child processes launched via system() inherit the closed FDs, and shells enter a non-conforming state where backgrounded subprocesses silently fail to execute. The fix uses open("/dev/null", O_RDWR) + dup2() to match the behavior of daemon(0, 0).

Documentation

Testing

  • 6 new regression tests for daemonize FD behavior (tests/test_daemonize.cc)
  • .gitignore uses wildcard pattern for test binaries
  • CI now triggers on release branches (0.*) in addition to main

Upgrading

Drop-in replacement for v0.3.0. No configuration or CLI changes.

v0.2.1 - Background Command Fix

08 Apr 18:28
d247965

Choose a tag to compare

Released: April 8, 2026

Patch release fixing a regression where commands containing backgrounded subprocesses (command &) silently failed in legacy mode.

Bug Fix

  • Fix background commands silently failing in legacy mode (#17) -- daemonize() was closing file descriptors 0-2 instead of redirecting them to /dev/null. This violates POSIX: child processes launched via system() inherit the closed FDs, and shells enter a non-conforming state where backgrounded subprocesses silently fail to execute. The fix uses open("/dev/null", O_RDWR) + dup2() to match the behavior of daemon(0, 0).

Testing

  • 6 new regression tests for daemonize FD behavior (tests/test_daemonize.cc)
  • CI now triggers on release branches (0.*) in addition to master

Upgrading

Drop-in replacement for v0.2.0. No configuration or CLI changes.

v0.3.0 - Service Manager

05 Apr 04:09

Choose a tag to compare

Released: April 4th, 2026

Transforms frequent-cron from a single-purpose daemon into a full service manager. Register, start, stop, and monitor multiple named services with a SQLite registry, platform-native service integration, and log capture with rotation. Now runs on Linux, macOS, FreeBSD, and Windows.

What's New

Service Management CLI

  • frequent-cron install <name> --frequency=<ms> --command=<cmd> -- register a named service
  • frequent-cron remove <name> -- unregister and clean up
  • frequent-cron start <name> -- start a registered service
  • frequent-cron stop <name> -- stop a running service
  • frequent-cron status [name] -- show status of one or all services
  • frequent-cron list -- tabular display of all registered services
  • frequent-cron logs <name> -- view service log output
  • frequent-cron run -- explicit run subcommand (same as legacy mode)
  • Legacy mode preserved: frequent-cron --frequency=... --command=... still works identically

SQLite Service Registry

  • Services and their state tracked in a local SQLite database
  • Schema: services table (name, command, frequency, synchronous) + service_state table (status, PID, timestamps, execution count)
  • Cascade delete: removing a service cleans up its state automatically
  • WAL journal mode for concurrent access safety

Platform-Native Service Installation

  • Linux: install generates systemd unit files at /etc/systemd/system/ (root) or ~/.config/systemd/user/ (user), runs systemctl daemon-reload
  • macOS: install generates launchd plists at ~/Library/LaunchAgents/ or /Library/LaunchDaemons/
  • FreeBSD: install generates rc.d scripts at /usr/local/etc/rc.d/, enables via sysrc
  • Windows: install registers with the Service Control Manager via Win32 CreateService API
  • remove cleans up all platform service definitions

Process Output Capture

  • New run_process() function captures stdout and stderr via popen
  • Executor supports optional OutputCallback for log capture
  • Falls back to system() when no callback is set (preserving exact legacy behavior)

Log Manager

  • Per-service log files at <data_dir>/logs/<name>.log
  • Timestamped entries
  • Size-based log rotation (default: 10MB, 5 rotated files)

Boot-Start and Auto-Restart

  • All platforms start services at boot when installed
  • Linux: Restart=on-failure with 5s delay via systemd
  • macOS: KeepAlive=true via launchd
  • FreeBSD: enabled at boot via sysrc; no auto-restart by default
  • Windows: SERVICE_AUTO_START via SCM; configure recovery with sc failure

Data Directory

  • Platform-specific defaults:
    • Linux: ~/.local/share/frequent-cron (user) or /var/lib/frequent-cron (root)
    • macOS: ~/Library/Application Support/frequent-cron
    • FreeBSD: ~/.local/share/frequent-cron (user) or /var/lib/frequent-cron (root)
    • Windows: %LOCALAPPDATA%\frequent-cron
  • Override with --data-dir=<path> on any subcommand
  • Auto-creates logs/ and pids/ subdirectories

Testing

  • 70 GTest unit tests: config (32), pid_file (3), executor (7), data_dir (4), database (12), process (5), log_manager (7)
  • Integration test suites for Linux/macOS/FreeBSD (bash) and Windows (PowerShell)
  • Per-platform CI workflows with individual badges: Linux, macOS, FreeBSD (via vmactions/freebsd-vm), Windows (with vcpkg binary caching)
  • Wiki auto-sync from docs/wiki/ to GitHub Wiki on push to master

Backward Compatibility

  • frequent-cron --frequency=1000 --command="echo hi" continues to work identically (legacy mode)
  • The run subcommand is functionally identical to legacy mode
  • No changes to the core timer/execution engine

New Dependencies

  • SQLite3 (libsqlite3-dev on Ubuntu, brew install sqlite on macOS, vcpkg install sqlite3:x64-windows)
  • CMake minimum version bumped from 3.5 to 3.14 (for GTest FetchContent)

Documentation

  • 14 wiki pages in docs/wiki/: Getting Started, CLI Reference, Service Management, Service Lifecycle, Architecture, Configuration, Logging, Platform Guides, FAQ, Troubleshooting, Contributing, and more
  • Release notes for all versions in docs/releases/
  • Updated platform guides for macOS, Ubuntu, and Windows
  • init_script.tpl moved to docs/ (prefer install subcommand for new setups)

New Files

  • include/: data_dir.h, database.h, service_registry.h, platform_service.h, log_manager.h, process_runner.h
  • src/: corresponding .cc implementations
  • tests/: test_data_dir.cc, test_database.cc, test_process.cc, test_log_manager.cc
  • docs/wiki/: 14 wiki pages
  • docs/releases/: release notes for all versions

v0.2.0 - Modernize and Expand Platform Support

04 Apr 23:48
0b0aa4b

Choose a tag to compare

Released: April 4, 2026

Modernized the codebase and added cross-platform support for macOS and Windows.

What's New

  • macOS support: builds and runs on macOS with Homebrew dependencies
  • Windows support: builds with MSVC + vcpkg, #ifdef _WIN32 guards throughout
  • Asynchronous execution mode: --synchronous=false launches commands via fork() (POSIX) or cmd /c start /b (Windows) for non-blocking execution
  • Modern C++: C++23, std::shared_ptr, std::chrono, std::ofstream replacing C-style I/O
  • Modern Boost ASIO: io_context + steady_timer replacing deprecated io_service + deadline_timer
  • Refactored architecture: split monolithic frequent.cc into config, executor, daemonize, pid_file modules with public headers in include/
  • GTest unit tests: 25 tests covering config parsing, PID file, executor behavior
  • Integration tests: bash (Linux/macOS) and PowerShell (Windows) test scripts
  • GitHub Actions CI: automated builds and tests on Linux, macOS, and Windows
  • make install and make test support
  • Platform documentation: installation guides for macOS (launchd), Ubuntu (systemd/init.d), and Windows (Task Scheduler)

Breaking Changes

  • CMake minimum version bumped from 2.8 to 3.5
  • C++23 standard required
  • Replaced daemon() with manual fork()/setsid() (removes macOS deprecation warning)
  • ParseResult::ERROR renamed to ParseResult::PARSE_ERROR (Windows macro conflict)

Dependencies

  • Boost 1.37+ (asio, program_options)
  • CMake 3.5+
  • C++23 compiler

v0.1.0 - Legacy Build

04 Apr 23:49

Choose a tag to compare

Released: October 28, 2011

The original release of frequent-cron. A single-file C++ daemon that runs shell commands at millisecond intervals on Linux.

Features

  • Millisecond-precision command scheduling via Boost ASIO deadline_timer
  • Blocking (synchronous) execution model
  • Daemonization via POSIX daemon()
  • PID file support for service lifecycle management
  • init.d service script template

Dependencies

  • Boost 1.37+ (system, program_options)
  • CMake 2.8+