# NousResearch/hermes-agent · PersistentShell polling causes excessive CPU on WSL

## Open now

- Nothing open on GitHub.

A fixed 10ms poll interval in PersistentShellMixin causes excessive resource consumption and high CPU usage, particularly on WSL/WSL2. Multiple fixes propose replacing it with exponential backoff.

## TL;DR

- 5 member(s): 0 open issue(s), 2 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 #2996. Verify it addresses your case.
- **Recommended:** read PR #2996 (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: `partially_resolved` · deciding PR(s): `pr-2996`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_PARTIAL`): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
- Members outside that structural core may belong to a different underlying problem.
- Pairwise link density `0.34`: 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

- #2784: \[Bug\]: PersistentShellMixin 10ms poll interval causes excessive resource consumption on WSL
- #31513: \[WSL2\] Gateway idle causes 100% CPU from wslhost on Windows 10

## Prior & competing PRs

- **#2996: fix(shell): exponential backoff for persistent shell polling**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `tools/environments/persistent_shell.py`, `tools/environments/ssh.py`
  - fix hunks:
  - `tools/environments/persistent_shell.py`

    ```diff
    @@ -40,7 +40,8 @@ def _execute_oneshot(self, command: str, cwd: str, *,
         def _cleanup_temp_files(self): ...
     
         _session_id: str = ""
    -    _poll_interval: float = 0.01
    +    _poll_interval_start: float = 0.01  # initial poll interval (10ms)
    +    _poll_interval_max: float = 0.25    # max poll interval (250ms) — reduces I/O for long commands
     
         @property
         def _temp_prefix(self) -> str:
    ```

    ```diff
    @@ -224,7 +225,7 @@ def _execute_persistent_locked(self, command: str, cwd: str,
             )
             self._send_to_shell(ipc_script)
             deadline = time.monotonic() + timeout
    -        poll_interval = self._poll_interval
    +        poll_interval = self._poll_interval_start  # starts at 10ms, backs off to 250ms
     
             while True:
                 if is_interrupted():
    ```

    ```diff
    @@ -256,6 +257,10 @@ def _execute_persistent_locked(self, command: str, cwd: str,
                     break
     
                 time.sleep(poll_interval)
    +            # Exponential backoff: fast start (10ms) for quick commands,
    +            # ramps up to 250ms for long-running commands — reduces I/O by 10-25x
    +            # on WSL2 where polling keeps the VM hot and memory pressure high.
    +            poll_interval = min(poll_interval * 1.5, self._poll_interval_max)
     
             output, exit_code, new_cwd = self._read_persistent_output()
             if new_cwd:
    ```
  - `tools/environments/ssh.py`

    ```diff
    @@ -87,7 +87,7 @@ def _establish_connection(self):
             except subprocess.TimeoutExpired:
                 raise RuntimeError(f"SSH connection to {self.user}@{self.host} timed out")
     
    -    _poll_interval: float = 0.15
    +    _poll_interval_start: float = 0.15  # SSH: higher initial interval (150ms) for network latency
     
         @property
         def _temp_prefix(self) -> str:
    ```
- **#2786: fix(shell): replace fixed 10ms poll interval with exponential backoff to reduce WSL2 resource consumption**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `#2996`
- **#2787: fix(tools):  exponential backoff for PersistentShellMixin poll interval   **. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#2786`

## Fix status

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