hermes - 💡(How to fix) Fix [Feature]: Allow interval-based cron jobs to specify a first-run anchor (decouple cadence from registration time) [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#18081Fetched 2026-05-01 05:54:00
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Author
Participants
Timeline (top)
labeled ×3

Fix Action

Fix / Workaround

Workarounds that don't work cleanly:

The only working workaround today is to create the job, then hand-edit ~/.hermes/cron/jobs.json to overwrite next_run_at. This works (scheduler honors the value on the next tick and subsequent +interval computations preserve the new cadence), but it's undocumented and requires reaching into internal storage.

The proposed first_run / anchor_at field is the smallest change that makes the common case ("biweekly reminder that aligns with an external event") possible without workarounds.

Code Example

cronjob(
    action="create",
    schedule="every 14d",
    first_run="2026-05-06T09:00:00+08:00",   # NEW: ISO timestamp
    prompt="...",
    name="FAB reminder",
)

---

hermes cron create "every 14d" --first-run 2026-05-06T09:00:00+08:00 ...
RAW_BUFFERClick to expand / collapse

Problem or Use Case

When creating a recurring every Nd / every Nh cron job, the first trigger is always now + interval. There is no way to tell the scheduler "I want this every 14 days, but the cadence should start from 2026-05-06 09:00 local, not from registration time."

Concrete example: Fab's "Limited-Time Free" assets drop every 14 days on Monday 21:59 Beijing time. I want a reminder every 14 days at 09:00 Tuesday (the morning after each drop). If I register every 14d today, the scheduler fires at registration + 14d, which lands at an arbitrary time of day and is off-cadence with the real event.

Workarounds that don't work cleanly:

  • Standard cron expressions (supported via croniter) have no native "every 2 weeks" semantics — 0 9 */14 * * fires on the 1st / 15th / 29th of the month, which is not a true 14-day cycle.
  • every 14d correctly preserves 14-day spacing once it starts, but offers no way to pick the starting point.

The only working workaround today is to create the job, then hand-edit ~/.hermes/cron/jobs.json to overwrite next_run_at. This works (scheduler honors the value on the next tick and subsequent +interval computations preserve the new cadence), but it's undocumented and requires reaching into internal storage.

For reference, OpenClaw — a sibling project with similar ergonomics — stored this as a first-class anchorMs field on every interval schedule, so the {interval, anchor} tuple fully pinned the cadence regardless of when the job was registered.

Proposed Solution

Extend the interval schedule with an optional anchor / first-run timestamp:

cronjob(
    action="create",
    schedule="every 14d",
    first_run="2026-05-06T09:00:00+08:00",   # NEW: ISO timestamp
    prompt="...",
    name="FAB reminder",
)

CLI parity:

hermes cron create "every 14d" --first-run 2026-05-06T09:00:00+08:00 ...

Semantics:

  • If first_run is in the future, the job fires at that exact time, then every N thereafter.
  • If first_run is in the past, compute the next occurrence as anchor + ceil((now - anchor) / interval) * interval (so you can pin a cadence that's been running since last year without needing to update the anchor).
  • Store the anchor alongside minutes in the schedule dict — e.g. {"kind": "interval", "minutes": 20160, "anchor_at": "2026-05-06T09:00:00+08:00"}. mark_job_run() can keep doing next_run_at += interval as today; the anchor is only consulted on create and (optionally) when cron run reschedules.

Alternatives Considered

  1. Keep using next_run_at hand-edits. Works, but invisible to users — the docs don't mention it, and it creates an ergonomics cliff between every and cron expressions.
  2. Rely on cron expressions alone. Doesn't solve it — cron grammar has no 14-day-cycle primitive (the classic Unix cron limitation).
  3. Encode the anchor into a cron expression with a # week-of-month modifier. Too fragile for arbitrary cadences like every 10 / 14 / 21 days, and croniter coverage varies.

The proposed first_run / anchor_at field is the smallest change that makes the common case ("biweekly reminder that aligns with an external event") possible without workarounds.

Feature Type

CLI improvement (also touches scheduler internals)

Scope

Small — likely touches:

  • cron/jobs.pyparse_schedule accepting the second param; JobSpec / create schema.
  • cron/scheduler.py — anchor-aware initial next_run_at computation on create.
  • The cronjob tool schema (new optional first_run field).
  • Tests: add coverage in tests/cron/test_jobs.py and tests/cron/test_scheduler.py.

Contribution

I'd be happy to submit a PR if the direction is accepted.

extent analysis

TL;DR

To fix the issue with recurring cron jobs not allowing a custom start time, add an optional first_run or anchor timestamp to the interval schedule.

Guidance

  • Introduce a new optional first_run parameter to the cronjob function and CLI, allowing users to specify the first run time of the job.
  • Update the scheduler to use this first_run value to calculate the initial next_run_at time, ensuring the job fires at the specified time and then every interval thereafter.
  • Store the first_run value alongside the interval in the schedule dict, allowing for easy retrieval and calculation of future run times.
  • Consider adding tests to cover this new functionality, including scenarios where first_run is in the past or future.

Example

cronjob(
    action="create",
    schedule="every 14d",
    first_run="2026-05-06T09:00:00+08:00",   # NEW: ISO timestamp
    prompt="...",
    name="FAB reminder",
)

Notes

This solution assumes that the croniter library is already being used to parse and handle cron expressions. The proposed change is a small extension to the existing interval schedule functionality.

Recommendation

Apply the proposed workaround by adding the first_run parameter to the cronjob function and CLI, as it provides a clean and user-friendly solution to the problem.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - 💡(How to fix) Fix [Feature]: Allow interval-based cron jobs to specify a first-run anchor (decouple cadence from registration time) [1 participants]