Skip to main content

Run a session

A desktop environment has two modes. Both act on the same machine, and differ in how the agent drives it. In shell mode, the agent gets a shell on your machine, running as you. It runs commands, reads and edits files, installs what a task needs, and starts tests and servers. When a result only shows in a window, it drives the screen and your Chrome from the same shell. Two guards bound what it does. It asks before a command you have not allowed, and its commands run in a sandbox that writes in one folder and cannot read your credentials. The sandbox is on by default on macOS. On Linux and Windows it is off until you install it, so require approval there. Stop it with Esc twice, or holo local stop in any terminal, which stops every session driving this machine.
Install
It works on macOS, Linux, and Windows (with Git for Windows, whose bash runs the commands). Create an agent with a desktop environment in shell mode, once:
Then run it from the folder it should work in:
CLI
holo connects your machine, prints each step, and asks you before a command that needs approval. From Python, answer in code. On macOS, the first session asks for the desktop permissions the agent needs to see and drive the screen, and stops with an error until you grant them.

What the agent can do

The agent is told to stay in its folder unless the task names another place, to install tools there and not system-wide, and to leave your windows and processes as it found them. These are instructions. The limits are the two guards.

Where it works

The agent starts in its workspace, the folder its file tools act in.
  • Files you attach to a message land in files/ in the workspace.
  • With a guard on, the file tools act in the workspace only, and never inside a .git folder. Commands go where the sandbox lets them, when it is on.
  • With no guard on, commands and file tools reach whatever you can.

Approve commands

With "command_approval": "required", a command waits for your decision unless it starts with an allowed one. A command is allowed by:
  • The agent’s allowed_commands, such as ["git status", "npm test"].
  • What you chose to always allow on this machine, kept in ~/.config/hai/allowed-commands. It starts with cua, which drives your screen.
An allowed command covers every command that starts with it: git status covers git status --short, and not git stash. In a line that chains commands with &&, ;, or |, each one must be covered. Some syntax always waits, because the words do not say what runs: $(...), backticks, subshells, and redirection to a file. A held command shows in pending_approvals with the command and the reason, and the session waits on awaiting_tool_results. An approval runs that command once. A denial tells the agent why, so it can try another way. Where nobody can answer, the run ends: holo with --json or --quiet, a pipe, or a coding agent. A call still held when a session ends is denied.

Answer from code

wait_for_completion returns when the agent holds a call. Decide each one, then wait again:
Python
Python reads HAI_SHELL_WORKSPACE too: set it before you start the session.

Sandbox

On macOS, every command runs inside Anthropic’s sandbox-runtime. The SDK downloads it on your first session in shell mode, 41 MB under ~/.hai/sandbox-runtime. If the download fails, commands run as you, with a warning at each session. An agent asks for more in its mode: allowed_domains to reach other hosts, writable_folders to write elsewhere. What was added is printed when the session starts.
  • With github.com allowed, commands read public repositories over HTTPS. Your SSH keys and stored git credentials stay unreadable, so the agent commits and you push.
  • "sandbox": "required" runs no command on a machine that cannot confine it.
  • Your own rules go in ~/.config/hai/sandbox.json, in sandbox-runtime’s settings format. The file replaces the built-in rules.
  • HAI_SHELL_SANDBOX=0 turns the sandbox off: commands then run as you.
  • The sandbox confines commands. It does not confine cua: what the agent does with your mouse and keyboard can do whatever you can.

Linux and Windows

There the sandbox is off until you install it and turn it on: with HAI_SHELL_SANDBOX=1, a sandbox.json, or an agent that requires it.
  • A command made only of cua calls runs outside the sandbox: that is how the agent sees and drives your screen. Mixed with anything else, cua stays inside and cannot reach it.
  • On Windows, commands run as a separate srt-sandbox user. Each takes several seconds, and curl cannot open HTTPS. git, pip, and node can. sandbox-runtime lists its known limitations.

Mode fields

The mode of the desktop environment, with "type": "shell". What your machine sets itself wins:
  • With HAI_SHELL_POLICY=<file>, that allowlist alone decides which commands wait, whatever the agent’s command_approval. allowed_commands is not added to it.
  • With a ~/.config/hai/sandbox.json, your file alone decides what commands reach and write. allowed_domains and writable_folders are not added to it.
  • With HAI_SHELL_SANDBOX=0, an agent that requires the sandbox does not start.

Behavior and limits

When a session starts, the SDK opens a connection inside your process. It receives the agent’s commands, runs them on your machine, and ties the session to it. Watch and steer and changes work as in the cloud.
  • One agent drives this machine at a time, and a run stops after 150 steps or 30 minutes by default, as on your desktop.
  • With a guard on, each command runs in a shell of its own: nothing carries from one to the next but the files.
  • Commands, their output, and the files the agent reads go to H with the session, as What H receives lays out.
  • The session file endpoints serve cloud browsers. Here the files are on your disk.
  • The connection closes when your process exits, and the sessions it served are cancelled.

Connect from elsewhere

The Python SDK and holo connect your machine for you, for an inline agent and for one referenced by name. For a session started from TypeScript, the H Platform, or another machine, serve the shell yourself and set the session_id it prints on the agent’s desktop environment:
CLI
holo local lists its flags.