# Tools

> What the agent can do (shell, file edits, a headless browser, subagents, other models, inline HTML) and how to turn each tool on or off.

Tools are what the model calls to act: run commands, edit files, drive a
browser. Each conversation gets its own set. The header at the top of a
conversation (something like "System Prompt: 8 tools, 11 skills") expands to
show exactly what it has.

## At a glance

| Tool | Default | For |
|---|---|---|
| `bash` | on | Running shell commands, with automatic backgrounding |
| `patch` | on | Exact text edits to files |
| `change_dir` | on | Moving the conversation's working directory |
| `output_iframe` | on | Showing HTML, charts, and diagrams inline |
| `subagent` | on | Delegating work to other conversations |
| `llm_one_shot` | on | A single prompt to a model, no tools or history |
| `browser` | on | Driving a headless Chrome |
| `read_image` | on | Showing the model an image file |
| `compact_in_place` | off | Letting the agent compact its own context ("Auto compaction") |
| `message_user` | off | Chat-style replies; by default you see only those |
| `message_parent` | automatic | How a subagent reports back to its parent |
| `web_search` | automatic | Provider-side web search |

Some tools depend on the model or the conversation:

- `subagent` exists only in top-level conversations; subagents can't spawn
  their own.
- `message_parent` is given to subagents and nothing else.
- `message_user` is offered only in top-level conversations.
- `read_image` is dropped for models that don't accept images.
- `web_search` runs on the provider's side and is added only for genuine
  Anthropic Claude models and OpenAI models on the Responses API.
- With OpenAI models that support it, `patch` is replaced by `apply_patch`,
  which takes Codex's patch format.

## Turning tools on and off

Open the model picker, then **Tools → Edit…**. Each tool can be *Default*,
*On*, or *Off*; *Apply to this conversation* records the change in the
transcript (it waits until the agent isn't working). To reuse a set of choices, save
it in a profile from the same picker; new conversations start from the
default profile. There is no command-line flag or `shelley.json` setting for
tools. Over the [API](https://github.com/boldsoftware/shelley/blob/main/API.md),
a new conversation takes `tool_overrides` (`{"browser": "off"}`) and
`disable_all_tools`.

## bash

Each call runs `bash --login -c` in the conversation's working directory with
no stdin. Nothing carries over between calls: a `cd` inside a command does
not move the conversation (that's `change_dir`'s job).

- **Backgrounding.** A command still running after 60 seconds moves to the
  background, and the model can start one there directly. Output goes to
  `$TMPDIR/shelley-jobs/<id>.log`. When the job exits, its conversation gets
  a message with the exit code and the log's tail, which starts a new turn if
  the agent is idle. Jobs keep running across a Shelley restart and are
  still reported. Kill one from the UI or with `kill -- -<PGID>`.
- **Stop** kills a foreground command's whole process group.
- **Big output** (over 50 KB) is written to a temp file; the model gets its
  path and the first and last few lines.
- **No interactive programs.** `EDITOR` is `/bin/false` and interactive
  rebases are refused. Long-running servers belong in `tmux`, which the tool
  description tells the model.
- **Environment.** Commands see `SHELLEY_CONVERSATION_ID`,
  `SHELLEY_CONVERSATION_SLUG`, `SHELLEY_MODEL`, `SHELLEY_CWD`,
  `SHELLEY_GIT_ROOT`, `SHELLEY_PORT`, `SHELLEY_URL`, `SHELLEY_SOCKET`, and
  `SHELLEY_USER_EMAIL` where they apply, plus `SKETCH=1`.
- **Guardrails, not security.** `git add -A`/`.`/`--all`/`*` and `rm -rf` on
  things like `.git`, `~`, or `/` are refused with a message asking for
  explicit paths. This catches mistakes; it does not contain anything. See
  [Running it safely](/docs/security).
- **Commit trailer.** `git commit` gets `Co-authored-by: Shelley
  <shelley@exe.dev>` appended. To turn that off:
  `git config --global shelley.no-trailer true`.
- **Missing commands.** When a command isn't installed, Shelley asks a model
  whether it's a well-known package and, if so, tries to install it with the
  system package manager (`sudo apt install -y …`, `brew install …`, and
  so on). This is always on. Where the package manager needs `sudo` and
  `sudo` needs a password, the install fails quietly.

## patch

Edits one file per call: `replace` (the old text must appear exactly once),
`append_eof`, `prepend_bof`, or `overwrite` (which also creates files). Every
successful edit renders as a diff in the transcript. Files changed through
`bash` don't get an inline diff; they show up in the
[diff viewer](/docs/conversations#diffs-git-graph-and-terminal).

## change_dir

Sets the working directory for later tool calls. The directory must exist;
relative paths resolve from the current one. The change is saved with the
conversation, shown in the status line, and the result tells the model
whether it's now in a git repository.

## output_iframe

Renders an HTML file from disk in the transcript, in an iframe sandboxed with
`allow-scripts allow-downloads` (no same-origin access). Scripts, styles, and
CDN resources work. Small local files (JSON, CSV, CSS, JS) can be bundled
along with it, and `excalidraw` is available as a hosted library, which the
built-in `excalidraw` skill uses for diagrams. The HTML is stored in the
conversation, so keep it small.

## browser

One tool with an `action` field: `navigate`, `eval`, `resize`, `screenshot`,
`console_logs`, plus families for device emulation, network logs,
accessibility queries, profiling, and screencasts. Screenshots are shown to
both you and the model.

- **Finding Chrome.** Shelley runs Chrome headless through
  [chromedp](https://github.com/chromedp/chromedp). On Linux it looks on
  `PATH` for `headless_shell`, `headless-shell`, `chromium`,
  `chromium-browser`, `google-chrome` (and its `-stable`, `-beta`,
  `-unstable` variants), or `chrome`, and also checks
  `/usr/local/bin/chrome` and `/snap/bin/chromium`. On macOS it checks only
  `/Applications/Chromium.app` and `/Applications/Google Chrome.app`. There is
  no setting to point it elsewhere. If nothing is found, the tool fails with
  "please apt install chromium or equivalent".
- **Lifecycle.** Each conversation gets its own browser, started on first use
  with a 1280×720 viewport and Chrome's sandbox off (`--no-sandbox`). It
  shuts down after 30 idle minutes.
- **Timeouts.** Actions default to 15 seconds; the model can pass a longer
  `timeout`.
- **Screencasts** record an MP4 and need `ffmpeg`. They stop on their own
  after 30 minutes or 10,000 frames.
- **Files.** Screenshots land in `/tmp/shelley-screenshots`, recordings in
  `/tmp/shelley-screencasts`, downloads in `/tmp/shelley-downloads`.

## read_image

Reads an image file and sends it to the model, converting HEIC and shrinking
anything over the model's size limits. Relative paths resolve against the
directory Shelley was started in, not the conversation's, so the model should
use absolute paths. You can comment on the image afterwards; see
[Conversations](/docs/conversations#the-composer).

## subagent

Starts a new conversation (identified by a slug) with a prompt, or sends a
further message to an existing one by reusing its slug. The call returns
immediately; the subagent works in the background and reports with
`message_parent`, which wakes the parent. A new subagent starts in the
parent's current directory, with the parent's model and reasoning level
unless the model picks others, and it does not see the parent's
conversation. Subagents show up nested under the parent in the conversation
list. Stopping the parent stops its working subagents.

## llm_one_shot

Sends one prompt to a model and returns the answer: no history, no tools.
The prompt is read from files, and images among them are attached. By default
it uses the conversation's model; the tool lists the others, and the model is
told to switch only when you ask ("get a second opinion from …"). Answers
over 4,000 bytes are written to an `llm-result-*.txt` file in the
working directory instead of being returned inline.

## compact_in_place and message_user

`compact_in_place` is the **Auto compaction** switch in the Tools dialog. The
agent lists its older context, then collapses ranges into short notes and
trims old tool output; it is nudged to do so once the context passes a
threshold (250k tokens by default, adjustable in the same dialog) and again
every 50k tokens after that. The original messages stay in the database.

`message_user` makes a conversation chat-style: you see your own messages and
what the agent sends with this tool, which can reply to or react to a
specific message of yours and attach files. The rest of its work is hidden
by default; the overflow menu's *Brevity* switch (*See All*) shows it.

## Beyond the built-ins

More capabilities come from [skills](/docs/skills), which the agent reads on
demand, and [MCP servers](/docs/mcp), which it reaches through the
`shelley mcp` command rather than as separate tools.
