Skip to main content
Use this guide when holo run, holo mcp, or holo acp starts but does not finish the desktop task.

Start with doctor

From the holo-desktop checkout:
uv run holo doctor
holo doctor is read-only. It checks the runtime binary, hosted or local model credentials, the agent API port, and the ~/.holo directory. Fix the first failing check before moving on.

Reproduce with the CLI

If the failure happened from MCP or ACP, reproduce the smallest version from a terminal first:
uv run holo run \
  --max-steps 5 \
  "Open TextEdit and write the word test"
For local mode, include the same base URL and model that the host uses:
uv run holo run \
  --base-url http://localhost:8000/v1 \
  --model Hcompany/Holo-3.1-35B-A3B \
  --max-steps 5 \
  "Open TextEdit and write the word test"
If the CLI works but the host does not, check host configuration, environment inheritance, and workspace scope.

Stop a bad run first

If HoloDesktop CLI is acting in the wrong app, typing in the wrong place, or looping, stop the active run before debugging:
uv run holo stop
For interactive CLI runs, you can also press Esc twice quickly. For MCP and ACP runs, double-Esc depends on the guard being installed and allowed to listen for key events. Normal stop is step-bounded: the CLI pauses and cancels the active run at the next safe point, so the in-flight action may complete first. If the runtime is stuck, use the force path:
uv run holo stop --force
After --force, restart the host if the MCP or ACP call stays blocked.

Check model mode

For hosted mode:
uv run holo whoami
If this fails, run:
uv run holo login
For local mode, confirm the OpenAI-compatible endpoint is reachable:
curl http://localhost:8000/v1/models
Then retry HoloDesktop CLI with --base-url. Local mode does not require holo login.

Check host environment

MCP and ACP hosts launch HoloDesktop CLI non-interactively. Hosted mode needs HAI_API_KEY available to that process, usually from ~/.holo/.env after uv run holo login. Local mode needs:
HAI_AGENT_RUNTIME_BASE_URL=http://localhost:8000/v1
and sometimes:
HAI_AGENT_RUNTIME_MODEL=Hcompany/Holo-3.1-35B-A3B
Terminal-launched hosts inherit shell exports. GUI apps launched from the Dock or Finder usually need these values in the host’s MCP or ACP environment settings. For Claude Code, also confirm you installed HoloDesktop CLI from the workspace where you are using Claude Code:
cd /path/to/your/claude-code-workspace
uv run holo install claude-code
Claude Code’s MCP CLI uses local scope by default, so the MCP server registration is associated with the workspace where the command ran.

Check runtime resolution

HoloDesktop CLI resolves hai-agent-runtime in this order:
  1. hai-agent-runtime on PATH
  2. managed install under ~/.holo/runtime/
  3. download-on-first-run
Run:
uv run holo doctor
The binary row shows which runtime path HoloDesktop CLI will use. If you are testing a local runtime build, put a deliberate hai-agent-runtime wrapper on PATH. Otherwise, let the CLI use the managed runtime.

Check logs

Runtime startup logs live under:
~/.holo/logs/
Per-run event logs live under:
~/.holo/runs/
To isolate one run, choose a temporary run directory:
uv run holo run \
  --runs-dir /tmp/holo-runs \
  --max-steps 5 \
  "Open TextEdit and write the word test"
For timing output, add:
--profile
Use runtime logs for startup, model, port, permission, and binary-resolution failures. Use run logs when the runtime started but the task failed, timed out, or acted in the wrong place.

Understand run logs

Each run writes a JSONL event log under:
~/.holo/runs/<run-id>/events.jsonl
For a normal holo run, the run directory usually contains events.jsonl. Observation events inside that file can include the raw screenshot HoloDesktop CLI saw as a base64 JPEG, plus metadata such as viewport size, cursor position, and sometimes accessibility data. Treat run logs as sensitive: they may contain screenshots, task text, app content, and model reasoning.
Do not post events.jsonl, ~/.holo/runs/, or screenshots from a run publicly without review. They can include what the model saw on screen, including account names, local paths, messages, documents, and secrets.
Each line is one timestamped runtime event. The exact JSON shape is diagnostic and may change, so do not build production integrations against it. Use the sequence to find where a failed run got stuck.
Event kindWhat it meansWhat to look for
message_eventThe task or follow-up message reached the runtimeConfirms the runtime received the task string you expected
observation_eventThe runtime captured or processed the visible desktop stateIf this is missing or followed by permission-looking errors, check Screen Recording
policy_eventThe model planned the next actionLook for the planned tool name and whether the action matches the task
tool_result or tool_result_eventA desktop action finished or failedLook for failed clicks, typing, app activation, or other tool errors
permission_requestThe runtime needs user approval for an app or capabilityGrant or deny in the UI, then retry if the runtime needs to restart
permission_decisionA permission request was granted or deniedDenied permissions explain missing screenshots, clicks, or typing
error_eventThe runtime surfaced an error during the sessionRead the error text, then check ~/.holo/logs/ for startup details
answer_eventThe runtime produced the final responseConfirms the run reached an end-of-turn rather than timing out
Example event lines:
{"ts":"2026-06-15T12:00:00Z","event":{"kind":"message_event","text_content":"Open TextEdit and write test"}}
{"ts":"2026-06-15T12:00:01Z","event":{"kind":"observation_event","observation":{"kind":"computer","image":{"type":"base64","media_type":"image/jpeg","source":"..."}}}}
{"ts":"2026-06-15T12:00:03Z","event":{"kind":"policy_event","tool_reqs":[{"tool_name":"click_desktop"}]}}
{"ts":"2026-06-15T12:00:05Z","event":{"kind":"tool_result","tool_req":{"tool_name":"click_desktop"}}}
{"ts":"2026-06-15T12:00:06Z","event":{"kind":"answer_event","answer":"done"}}
Here is a shortened real log sketch for a run whose prompt was Open Calculator and compute 2+2:
message_event
  content: Open Calculator and compute 2+2

observation_event
  The runtime saw the desktop. Viewport: 1920x1243. Screenshot: embedded JPEG.

policy_event
  note: open Calculator with Spotlight
  tool: hotkey_desktop {"keys": ["cmd", "space"]}

tool_result
  hotkey_desktop completed

policy_event
  note: type Calculator into Spotlight
  tool: write_desktop {"content": "Calculator", "overwrite": true}

tool_result
  write_desktop completed

policy_event
  note: press Enter to open Calculator
  tool: hotkey_desktop {"keys": ["enter"]}

tool_result
  hotkey_desktop completed

observation_event
  Calculator is visible.

policy_event
  note: click the plus button
  tool: click_desktop {"element": "Orange plus (+) button"}

tool_result
  click_desktop completed

policy_event
  note: click the 2 button
  tool: click_desktop {"element": "Number 2 button"}

tool_result
  click_desktop completed

observation_event
  Calculator shows 2+2.

answer_event
  Final answer says the calculator shows 2+2 and clicking equals would display 4.
This run reached answer_event, but the event sequence shows the runtime never clicked =. That distinction matters: the runtime completed from the agent’s perspective, but the task was not fully done. Use the sequence to localize the failure:
Log patternUsually means
No message_eventThe client did not create a session or wrote logs somewhere else
message_event but no observation_eventRuntime startup, screen capture, or permission problem
observation_event but no policy_eventModel backend did not respond, model request failed, or model was too slow
policy_event but no tool_result / tool_result_eventDesktop tool execution failed or hung
Repeated policy_event / tool_result pairsThe agent is acting, but may be looping or stuck on the UI
permission_request followed by denied permission_decisionThe run needs user approval before it can continue
error_event appearsThe session failed inside the runtime; read the error and runtime log together
answer_event is present but task result is wrongThe run completed from the agent’s perspective; improve the task string or inspect earlier actions
For timing summaries, prefer:
uv run holo run --profile "Open TextEdit and write the word test"
--profile reads the event log and prints per-step observe, model, tool, and total timings.

Check macOS permissions

On macOS, HoloDesktop CLI needs:
  • Screen Recording, to observe the desktop;
  • Accessibility, to click and type.
Grant permissions to the process that launches HoloDesktop CLI. For CLI runs, that is usually your terminal. For MCP or ACP, it may be the host app or the runtime process it starts. After granting permissions, restart the process that launched the CLI. Permission grants often do not apply to an already-running runtime process.

Common fixes

SymptomLikely causeTry
No HAI_API_KEY foundHosted mode is not signed inuv run holo login
Local endpoint works in terminal but not hostHost did not inherit env varsAdd env vars to host config or launch host from that shell
Claude Code cannot see HoloDesktop CLIInstalled in a different workspaceRe-run uv run holo install claude-code from the active workspace
Runtime starts but cannot observeScreen Recording missingGrant permission and restart the runtime
Runtime observes but cannot click/typeAccessibility missingGrant permission and restart the runtime
Double-Esc does not stop a host-launched runGuard is not installed, not running, or lacks Input MonitoringRe-run uv run holo install <host-id>, grant Input Monitoring, or use uv run holo stop
HoloDesktop CLI controls the wrong monitorTarget app is on a secondary displayMove the app to the primary display, mirror displays, or disconnect secondary monitors
--base-url run fails before contacting modelRuntime/config mismatchUpdate to the fixed runtime/client version and retry
Task times outTask is too broad or model is slowUse a smaller task, --max-steps, or a faster model

What’s next

Use MCP if the failure only happens inside an agent host.