# NousResearch/hermes-agent · Remove unnecessary crontab requirement from cronjob tool

## Open now

- Nothing open on GitHub.

A bug was reported that crontab is required even when crons are internal, followed by multiple fix attempts removing that unnecessary dependency from the cronjob tool.

## TL;DR

- 4 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 2 PR(s) closed without merging.
- A fix was merged to main in PR #1638. Verify it addresses your case.
- **Recommended:** read PR #1638 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `resolved` · deciding PR(s): `pr-1638`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.50`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #1589: \[Bug\]: Crontab is required despite crons being internal?

## Prior & competing PRs

- **#1638: fix(tools): remove unnecessary crontab requirement from cronjob tool**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `tests/tools/test_cronjob_tools.py`, `tools/cronjob_tools.py`
  - fix hunks:
  - `tests/tools/test_cronjob_tools.py`

    ```diff
    @@ -62,22 +62,44 @@ def test_deception_blocked(self):
     
     
     class TestCronjobRequirements:
    -    def test_requires_crontab_binary_even_in_interactive_mode(self, monkeypatch):
    +    def test_requires_no_crontab_binary(self, monkeypatch):
    +        """Cron is internal (JSON-based scheduler), no system crontab needed."""
             monkeypatch.setenv("HERMES_INTERACTIVE", "1")
             monkeypatch.delenv("HERMES_GATEWAY_SESSION", raising=False)
             monkeypatch.delenv("HERMES_EXEC_ASK", raising=False)
    -        monkeypatch.setattr("shutil.which", lambda name: None)
    -
    -        assert check_cronjob_requirements() is False
    +        # Even with no crontab in PATH, the cronjob tool should be available
    +        # because hermes uses an internal scheduler, not system crontab.
    +        assert check_cronjob_requirements() is True
     
    -    def test_accepts_interactive_mode_when_crontab_exists(self, monkeypatch):
    +    def test_accepts_interactive_mode(self, monkeypatch):
             monkeypatch.setenv("HERMES_INTERACTIVE", "1")
             monkeypatch.delenv("HERMES_GATEWAY_SESSION", raising=False)
             monkeypatch.delenv("HERMES_EXEC_ASK", raising=False)
    -        monkeypatch.setattr("shutil.which", lambda name: "/usr/bin/crontab")
     
             assert check_cronjob_requirements() is True
     
    +    def test_accepts_gateway_session(self, monkeypatch):
    +        monkeypatch.delenv("HERMES_INTERACTIVE", raising=False)
    +        monkeypatch.setenv("HERMES_GATEWAY_SESSION", "1")
    +        monkeypatch.delenv("HERMES_EXEC_ASK", raising=False)
    +
    +        assert check_cronjob_requirements() is True
    +
    +    def test_accepts_exec_ask(self, monkeypatch):
    +        monkeypatch.delenv("HERMES_INTERACTIVE", raising=False)
    +        monkeypatch.delenv("HERMES_GATEWAY_SESSION", raising=False)
    +        monkeypatch.setenv("HERMES_EXEC_ASK", "1")
    +
    +        assert check_cronjob_requirements() is True
    +
    +    def test_rejects_when_no_session_env(self, monkeypatch):
    +        """Without any session env vars, cronjob tool should not be available."""
    +        monkeypatch.delenv("HERMES_INTERACTIVE", raising=False)
    +        monkeypatch.delenv("HERMES_GATEWAY_SESSION", raising=False)
    +        monkeypatch.delenv("HERMES_EXEC_ASK", raising=False)
    +
    +        assert check_cronjob_requirements() is False
    +
     
     # =========================================================================
     # schedule_cronjob
    ```
  - `tools/cronjob_tools.py`

    ```diff
    @@ -8,7 +8,6 @@
     import json
     import os
     import re
    -import shutil
     import sys
     from pathlib import Path
     from typing import Any, Dict, List, Optional
    ```

    ```diff
    @@ -414,13 +413,10 @@ def check_cronjob_requirements() -> bool:
         """
         Check if cronjob tools can be used.
     
    -    Requires 'crontab' executable to be present in the system PATH.
         Available in interactive CLI mode and gateway/messaging platforms.
    +    The cron system is internal (JSON file-based scheduler ticked by the gateway),
    +    so no external crontab executable is required.
         """
    -    # Ensure the system can actually install and manage cron entries.
    -    if not shutil.which("crontab"):
    -        return False
    -
         return bool(
             os.getenv("HERMES_INTERACTIVE")
             or os.getenv("HERMES_GATEWAY_SESSION")
    ```
- **#1610: fix(tools): remove unnecessary crontab dependency from cronjob tools**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#1638`, `#1633`
- **#1633: fix(tools): remove unnecessary crontab requirement from cronjob tool**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#1638`

## Fix status

- Merged to main in PR #1638 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-03-17`. This confirmation is old and may be out of date (a revert/reopen would not have invalidated it here); re-verify.
- Subsystem: `cron`
