> Index of all guides: https://hither.dev/llms.txt. Agents start at https://hither.dev/skill.md.

# Use the computer

For agents with an active connection. Get exact inputs from `tools/list`. MCP tool names use underscores (`files_read`) and REST operation names use dots (`files.read`). Numbers are in [limits](how-it-works.md#limits).

Every operation takes `deviceId` from `devices`. An optional `requestId` must be a fresh UUID; the service rejects a reused one and doesn't replay its result. An optional `deadlineInMs` makes the helper refuse a call that arrives late. It doesn't cancel a running command.

## Read or change a file

- `files_read` with `path`, absolute or starting with `~/`. Without `limit` it returns the whole file. Page a large file with `offset` (zero-based line) and `limit`, or `tail: true`.
- `files_write` with `path` and `content` replaces the whole file.
- `files_edit` with `path`, `oldText` and `newText` replaces text that matches exactly once.

Write a file back only after a read with `status: "complete"`. Writing back a partial read deletes the rest. Binary and oversized files need [transfers](#transfer-files).

## List and search

`files_list` takes `path`, `depth` and `limit`. `files_stat` returns size, type and modification time. `files_search` takes `path`, a literal `query`, and `mode` (`names` or `content`), and returns the first matching line per file. `timeoutMs` and `maxBytes` raise its budget.

| `status` | Meaning | Do |
| --- | --- | --- |
| `complete` | The requested range is covered. | Done. An empty result means nothing matched. |
| `partial` | Another page exists, or files were skipped. | Call again with `cursor` and the same options. |
| `truncated` | It hit a size or entry budget. | Raise `limit` or `maxBytes`, or narrow `path`. |
| `timed_out` | It hit the time budget. | Continue with `cursor`, or narrow `path`. |

`skipped` names binary, oversized and unreadable files and symlinked folders; keep it across pages. Report what you could not cover.

## Run a command

`shell_exec` with `command`, and optional `cwd` and `timeoutMs`. Check `code`, `stdout` and `stderr`. A nonzero `code` means the command ran and failed.

When the Terminal sandbox refuses something, the result has `sandbox.blocked: true` and `stderr` has a `<sandbox_violations>` block naming what was refused. Tell the person and drop that approach. `update_helper_for_terminal_sandbox` means the helper is too old to sandbox, so the person must run setup again or allow full access.

## Keep a Terminal session

Use a session for commands that may run longer than 30 seconds, servers and prompts.

1. `shell_start` with `command`, and optional `cwd` and `idleMinutes`. Save `sessionId`.
2. `shell_read` with `sessionId` and `cursor`, starting at `0`. Pass the returned `cursor` back unchanged. `more: true` means output is waiting, `bytesDropped` above 0 means some output was lost, and `running` and `code` show whether the process exited.
3. `shell_write` with `sessionId` and `input`. End a line with a newline.
4. `shell_status`, `shell_list` and `shell_kill` inspect or stop sessions.

Sessions use pipes, so programs that need a TTY fail. A background job (`cmd &`) dies with the session's shell, so end the command with `wait`. A session ends when it sits idle or when the connection ends. Sessions run in the same sandbox as `shell_exec`.

## Transfer files

Small upload: `transfer_start` with `path`, `transfer_chunk` with `transferId`, `index` from 0 and `base64` per chunk, then `transfer_finish`. Small download: `transfer_pull` with `path`, repeating with `offset` set to `nextOffset` until `done` is true.

Large download:

1. `bulk_export` with `path`.
2. `bulk_status` with `transferId` until `status` is `ready`.
3. Fetch `downloadUrl` with your own tool and save the bytes yourself. A hosted MCP server can't write to your disk.

Large upload:

1. `bulk_upload` with the exact byte `size`.
2. PUT each `partSize` slice to `uploadUrl` with a `partNumber` query parameter added, from 1, keeping the other parameters. Send `Content-Length` and `X-Content-SHA256`, the part's lowercase hex SHA-256. An empty file is one empty part.
3. POST `completeUrl`.
4. `bulk_import` with `transferId` and the destination `path`, then `bulk_status` until `completed` or `failed`.

Use one credential for the whole transfer and keep download links out of logs. `bulk_cancel` deletes the cloud copy, not a file already delivered. Over REST, send a UUID `requestId` to `bulk.export` or `bulk.upload`. It becomes the `transferId`, so a lost response is recovered with `bulk.status`, not a second start.

## Use the browser

Browser access covers every tab in the approved profile, including signed-in sites.

1. `browser_call` with `name: "tools/list"`, then `browser_call` with a returned tool as `name` and its `arguments`.
2. For sign-ins the person imported, call `name: "profiles/list"` and pass the chosen `profile` UUID on every call. Leave out `browser`.

`browser_installing` means Chromium is still downloading and nothing ran. Wait a few seconds and call again; it is the one error you retry. The person imports sign-ins on the computer, as [browser sign-ins](browser-sessions.md) describes.

## Use the computer's MCP servers

`mcp_servers` lists servers configured on the computer for Claude, Claude Code, Codex, Cursor or Windsurf, without their commands or secrets. Then `mcp_tools` with `server`, and `mcp_call` with `server`, `tool` and `arguments`. Stdio servers start for one call. They run with their own permissions, outside the Terminal sandbox.

## When the computer is offline

`device_offline` means nothing ran. Drop the work, or queue it. Queueing work the person already asked for needs no new confirmation.

1. `queue_operation` with `deviceId`, a dotted `operation` such as `files.read`, `args`, and a fresh `requestId`. For a different deadline, pass `expiresInSeconds`, or `waitUntil` as `"3 hours"`, `"3:30pm"` with an IANA `timeZone`, or an ISO time.
2. Tell the person the work is waiting. The reply has `jobId` and the deadline it settled on as `waitUntil`.
3. Call `job_wait` once with `jobId`. It returns `completed`, `failed`, `cancelled`, `expired` or `outcome_unknown`. If your host drops the call, call `job_wait` again with the same `jobId` instead of polling `job_status`.
4. `job_cancel` stops a queued job. `cancelled: false` means it already went out.

A job never outlives its connection, and the service rechecks permissions before sending it. `job_result_too_large` means it may have run but the result wasn't kept. Hosts with MCP task support can run `job_wait` as a task. REST uses `POST /api/jobs`, then `/api/jobs/wait`, `/status` or `/cancel` with `{"jobId": "..."}`.

## Resolve an uncertain outcome

`outcome_unknown` means the call may have run. Never retry it automatically or with a new `requestId`, because a new ID is new work.

1. Call `resolve_operation` with `deviceId` and `requestId`, or `POST /api/operations/resolve`. It never runs anything.
2. Act on `state`:

| `state` | Meaning | Do |
| --- | --- | --- |
| `finished` | It ran. `reply` has the result, minus the body if `resultTruncated`. | Use the reply. |
| `running` | It started and hasn't finished. | Resolve again later. |
| `refused_expired` | It never started. | Send it as new work if still needed. |
| `unknown` | Helper offline, no record, or restarted. Read-only calls always land here and are safe to retry. | Go to step 3. |

3. Check `operations` and whatever the call would have changed, then tell the person what you couldn't establish.
