hermes - 💡(How to fix) Fix [Bug]: hermes tools does not install cua-driver for returning users (Computer Use docs broken)

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…

Error Message

"Installing cua-driver..." line. No warning. No error.

Additional Logs / Traceback

Launch blocker for the cua x Hermes integration. The docs' Enabling step 1 is the canonical path users will follow on the launch announcement. A clean-room user reading the docs will install Hermes, run hermes tools, see "saved", try hermes -t computer_use chat, hit the backend-unavailable error, re-read the docs, and conclude either Hermes or cua-driver is broken.

Root Cause

There are two independent bugs that compound. Either one alone is sufficient to break the docs contract; both must be fixed.

Fix Action

Fix / Workaround

The toggle-off / toggle-on workaround across two separate hermes tools invocations also does not work — the post-setup is gated out for a distinct reason (see Root Cause #2 below).

added is the diff between the picker's open-state and save-state. When a user opens the picker, unchecks computer_use, then re-checks it in the same session before saving, added is empty. The two-runs workaround (uncheck+save, reopen, check+save) makes added non-empty — but that path is fully gated out by Bug 2.

Why other workarounds don't work

Code Example

# 1. Install Hermes (fresh)
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
source ~/.zshrc

# 2. Run setup once (doesn't matter what you select; just complete it)
hermes setup

# 3. Confirm cua-driver is NOT installed
which cua-driver        # => not found
ls /Applications/CuaDriver.app   # => No such file

# 4. Follow the docs: enable Computer Use via `hermes tools`
hermes tools
#    - find "🖱️ Computer Use (macOS)" in the picker
#    - check it (space)
#    - confirm/save
#    - exit picker

# 5. Wizard prints `✓ Saved configuration` and exits cleanly. No
#    "Installing cua-driver..." line. No warning. No error.

# 6. Verify nothing was installed
which cua-driver        # => still not found
ls /Applications/CuaDriver.app   # => still missing

# 7. Try to use Computer Use
hermes -t computer_use chat
#    First capture call → "computer_use backend unavailable:
#    cua-driver is not installed"

---

computer_use backend unavailable: cua-driver is not installed
hint: Run `hermes tools` and enable Computer Use to install cua-driver.

---

# ~/.hermes/config.yaml
toolsets:
  - hermes-cli
platform_toolsets:
  cli:
    - browser
    - clarify
    - code_execution
    - computer_use     # <-- present, but cua-driver was never installed
    - cronjob
    ...

---

$ which cua-driver
cua-driver not found
$ ls /Applications/CuaDriver.app
ls: /Applications/CuaDriver.app: No such file or directory

---

for ts_key in sorted(added):
    if (TOOL_CATEGORIES.get(ts_key) or TOOLSET_ENV_REQUIREMENTS.get(ts_key)):
        if _toolset_needs_configuration_prompt(ts_key, config):
            _configure_toolset(ts_key, config)

---

def _toolset_needs_configuration_prompt(ts_key: str, config: dict) -> bool:
    cat = TOOL_CATEGORIES.get(ts_key)
    if not cat:
        return not _toolset_has_keys(ts_key, config)

    if ts_key == "tts":   ...
    if ts_key == "web":   ...
    if ts_key == "browser":   ...
    if ts_key == "image_gen":   ...

    return not _toolset_has_keys(ts_key, config)   # <-- catch-all

---

cat = TOOL_CATEGORIES.get(ts_key)
if cat:
    for provider in _visible_providers(cat, config):
        env_vars = provider.get("env_vars", [])
        if not env_vars:
            return True  # No-key provider (e.g. Local Browser, Edge TTS)

---

def _toolset_needs_configuration_prompt(ts_key: str, config: dict) -> bool:
    cat = TOOL_CATEGORIES.get(ts_key)
    if not cat:
        return not _toolset_has_keys(ts_key, config)

    # If any visible provider has a post-setup that hasn't been satisfied
    # yet (e.g. cua-driver binary not installed), we still need to run
    # the configuration flow so the post-setup hook fires.
    for provider in _visible_providers(cat, config):
        post_setup = provider.get("post_setup")
        if post_setup and not _post_setup_already_done(post_setup):
            return True

    if ts_key == "tts":   ...
    # ... rest unchanged
RAW_BUFFERClick to expand / collapse

Bug Description

The Computer Use (macOS) docs at website/docs/user-guide/features/computer-use.md say:

  1. Run hermes tools, pick 🖱️ Computer Use (macOS)cua-driver (background).
  2. The setup runs the upstream installer: curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/cua-driver/scripts/install.sh.

For an already-configured user (i.e. anyone who has run hermes setup once), this contract is broken: hermes tools toggles computer_use on, prints a green ✓ Saved configuration banner, but never invokes the cua-driver post-setup hook, never runs the upstream installer, and prints no warning. The user thinks Computer Use is enabled, then hits computer_use backend unavailable: cua-driver is not installed on first use.

There is no documented or discoverable way through hermes tools for an existing user to trigger the cua-driver install. The only working paths are running the upstream install.sh manually or going through the first-time setup wizard (which doesn't apply on subsequent runs).

This makes the docs' headline-1 instruction non-functional in the modal case, which is launch-blocking for the cua x Hermes integration.

Steps to Reproduce

Clean macOS, no prior Hermes / cua-driver installation. Reproduces both on the curl one-liner install and on ./setup-hermes.sh (dev install).

# 1. Install Hermes (fresh)
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
source ~/.zshrc

# 2. Run setup once (doesn't matter what you select; just complete it)
hermes setup

# 3. Confirm cua-driver is NOT installed
which cua-driver        # => not found
ls /Applications/CuaDriver.app   # => No such file

# 4. Follow the docs: enable Computer Use via `hermes tools`
hermes tools
#    - find "🖱️ Computer Use (macOS)" in the picker
#    - check it (space)
#    - confirm/save
#    - exit picker

# 5. Wizard prints `✓ Saved configuration` and exits cleanly. No
#    "Installing cua-driver..." line. No warning. No error.

# 6. Verify nothing was installed
which cua-driver        # => still not found
ls /Applications/CuaDriver.app   # => still missing

# 7. Try to use Computer Use
hermes -t computer_use chat
#    First capture call → "computer_use backend unavailable:
#    cua-driver is not installed"

The toggle-off / toggle-on workaround across two separate hermes tools invocations also does not work — the post-setup is gated out for a distinct reason (see Root Cause #2 below).

Expected Behavior

Per the docs at website/docs/user-guide/features/computer-use.md:30-32: running hermes tools and selecting 🖱️ Computer Use (macOS)cua-driver (background) should subprocess the upstream install.sh, drop /Applications/CuaDriver.app and ~/.local/bin/cua-driver, and print a permissions reminder. The cua_driver post-setup hook at hermes_cli/tools_config.py:660-705 already implements exactly this — it just isn't reachable from the picker on the returning-user path.

Actual Behavior

Picker writes computer_use into platform_toolsets.cli in ~/.hermes/config.yaml and exits with ✓ Saved configuration. No post-setup is invoked. No cua-driver binary is installed. No warning is printed. First runtime use of computer_use fails with:

computer_use backend unavailable: cua-driver is not installed
hint: Run `hermes tools` and enable Computer Use to install cua-driver.

— but following that hint does nothing, looping the user.

Affected Component

  • Tools (terminal, file ops, web, code execution, etc.)
  • Setup / Installation
  • Configuration (config.yaml, .env, hermes setup)

Messaging Platform

N/A (CLI only)

Debug Report

Pending — will append once hermes debug share is run on a clean repro.

Operating System

macOS 15.4 (Darwin 25.4.0, arm64)

Python Version

3.11.15

Hermes Version

v0.13.0 (2026.5.7) — also reproduces on main at 0cafe7d50.

Additional Logs / Traceback

~/.hermes/logs/agent.log shows nothing relevant — the picker codepath runs entirely in-process and the _run_post_setup function is never called for cua_driver. There is no log entry to point at because the silent skip happens above any logging.

Configuration evidence — after hermes tools "saves" computer_use:

# ~/.hermes/config.yaml
toolsets:
  - hermes-cli
platform_toolsets:
  cli:
    - browser
    - clarify
    - code_execution
    - computer_use     # <-- present, but cua-driver was never installed
    - cronjob
    ...
$ which cua-driver
cua-driver not found
$ ls /Applications/CuaDriver.app
ls: /Applications/CuaDriver.app: No such file or directory

Root Cause Analysis

There are two independent bugs that compound. Either one alone is sufficient to break the docs contract; both must be fixed.

Bug 1 — Toggle in a single picker session is a no-op

Returning-user save path at hermes_cli/tools_config.py:2337-2340:

for ts_key in sorted(added):
    if (TOOL_CATEGORIES.get(ts_key) or TOOLSET_ENV_REQUIREMENTS.get(ts_key)):
        if _toolset_needs_configuration_prompt(ts_key, config):
            _configure_toolset(ts_key, config)

added is the diff between the picker's open-state and save-state. When a user opens the picker, unchecks computer_use, then re-checks it in the same session before saving, added is empty. The two-runs workaround (uncheck+save, reopen, check+save) makes added non-empty — but that path is fully gated out by Bug 2.

Bug 2 — _toolset_needs_configuration_prompt excludes no-key providers

hermes_cli/tools_config.py:1395-1430:

def _toolset_needs_configuration_prompt(ts_key: str, config: dict) -> bool:
    cat = TOOL_CATEGORIES.get(ts_key)
    if not cat:
        return not _toolset_has_keys(ts_key, config)

    if ts_key == "tts":   ...
    if ts_key == "web":   ...
    if ts_key == "browser":   ...
    if ts_key == "image_gen":   ...

    return not _toolset_has_keys(ts_key, config)   # <-- catch-all

For computer_use, the catch-all returns not _toolset_has_keys(...). _toolset_has_keys at line 1188-1195 short-circuits to True for any provider with empty env_vars:

cat = TOOL_CATEGORIES.get(ts_key)
if cat:
    for provider in _visible_providers(cat, config):
        env_vars = provider.get("env_vars", [])
        if not env_vars:
            return True  # No-key provider (e.g. Local Browser, Edge TTS)

The cua-driver provider has empty env_vars (tools_config.py:461-465). So _toolset_has_keys("computer_use", config) returns True, and _toolset_needs_configuration_prompt returns False — meaning _configure_toolset (and therefore the entire _run_post_setup pipeline that contains the cua-driver install at lines 660-705) never runs for computer_use via the hermes tools returning-user path, regardless of added-set state.

The intent of _toolset_needs_configuration_prompt ("does this need API keys?") doesn't match the actual need ("does this need any provider setup at all, including a binary install?"). The first-time setup loop at line 2257-2258 calls _configure_toolset unconditionally for every selected toolset — which is why a fresh first-time setup would install cua-driver if the user selected it there. Returning users have no equivalent path.

Why other workarounds don't work

Attempted pathResult
hermes tools → check Computer Use → saveSaves config, no install (Bug 2)
hermes tools toggle off+on in one session, saveNo-op (Bug 1)
hermes tools uncheck+save, reopen, check+save (two sessions)Bug 1 sidestepped, Bug 2 still gates out the install
hermes setup (re-run for already-configured user)Behavior depends on whether the wizard re-enters first-time mode; not validated as a workaround in this report
Upstream install.sh curl one-linerWorks (this is what _run_post_setup would have done)

Proposed Fix

Either of the following independently fixes the docs contract; ideally ship both because they patch different invariants.

Fix A — Make _toolset_needs_configuration_prompt honor post_setup

At hermes_cli/tools_config.py:1395-1430, add an early-return when any visible provider has a post_setup whose installed-state predicate fails:

def _toolset_needs_configuration_prompt(ts_key: str, config: dict) -> bool:
    cat = TOOL_CATEGORIES.get(ts_key)
    if not cat:
        return not _toolset_has_keys(ts_key, config)

    # If any visible provider has a post-setup that hasn't been satisfied
    # yet (e.g. cua-driver binary not installed), we still need to run
    # the configuration flow so the post-setup hook fires.
    for provider in _visible_providers(cat, config):
        post_setup = provider.get("post_setup")
        if post_setup and not _post_setup_already_done(post_setup):
            return True

    if ts_key == "tts":   ...
    # ... rest unchanged

…with a small registry mapping each post_setup key to its installed-state predicate (e.g. "cua_driver": lambda: shutil.which("cua-driver") is not None, "agent_browser": lambda: (PROJECT_ROOT / "node_modules" / "agent-browser").exists(), etc.). Centralises the installed-state check that's currently scattered across the post-setup hooks themselves.

This also fixes Bug 1 incidentally: when the install is already done, the gate returns False and no-op toggles remain no-ops; when the install isn't done, the gate returns True and toggling computer_use on triggers the install regardless of added-set state — which matches user expectation and the docs' contract.

Fix B — Add a dedicated hermes computer-use install command

Sidesteps the picker plumbing entirely and gives the docs a stable target. The implementation is one call to _run_post_setup("cua_driver"). Three-line CLI wiring; easy to review.

Fix C — Docs band-aid (not recommended alone)

Update computer-use.md:30-32 to recommend hermes setup (which routes through the first-time loop that calls _configure_toolset unconditionally). Risk: behaviour for already-configured users hasn't been validated and may itself be a no-op. Plus the silent failure mode of hermes tools remains in place for anyone who follows existing tutorials, blog posts, or muscle memory.

Severity / Launch-Blocker Classification

Launch blocker for the cua x Hermes integration. The docs' Enabling step 1 is the canonical path users will follow on the launch announcement. A clean-room user reading the docs will install Hermes, run hermes tools, see "saved", try hermes -t computer_use chat, hit the backend-unavailable error, re-read the docs, and conclude either Hermes or cua-driver is broken.

Are you willing to submit a PR for this?

Coordinating with cua (trycua) and Nous (NousResearch) teams first.

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