> ## Documentation Index
> Fetch the complete documentation index at: https://mux-advisor-0dak.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Tool Hooks

> Block dangerous commands, lint after edits, and set up your environment

<Note>Tool hooks are experimental. Expect breaking changes while we iterate.</Note>

<Tip>
  **The easiest way to set up tool hooks is to ask Mux.** Just tell Mux what you want (e.g., "lint
  Python files after edits" or "block force pushes") and it will create the hook scripts for you.
</Tip>

Tool hooks let you run your own scripts before and after Mux tool executions.

## What do you want to do?

<CardGroup cols={3}>
  <Card title="Block dangerous commands" icon="shield" href="#block-dangerous-commands">
    Prevent force pushes, rm -rf, etc.
  </Card>

  <Card title="Lint after file edits" icon="check" href="#lint-after-file-edits">
    Run ruff, eslint, tsc after changes
  </Card>

  <Card title="Set up environment" icon="gear" href="#set-up-environment">
    direnv, nvm, virtualenv
  </Card>
</CardGroup>

***

## Block dangerous commands

Create `.mux/tool_pre` to validate commands before they run. Exit non-zero to block:

```bash theme={null}
#!/usr/bin/env bash
# .mux/tool_pre - runs before every tool

if [[ "$MUX_TOOL" == "bash" ]]; then
  script="$MUX_TOOL_INPUT_SCRIPT"

  if echo "$script" | grep -q 'push.*--force'; then
    echo "❌ Force push blocked" >&2
    exit 1
  fi

  if echo "$script" | grep -q 'rm -rf /'; then
    echo "❌ Dangerous rm blocked" >&2
    exit 1
  fi
fi

exit 0  # Allow tool to run
```

```bash theme={null}
chmod +x .mux/tool_pre
```

The agent sees your error message and can adjust its approach.

***

## Lint after file edits

Create `.mux/tool_post` to run validation after tools complete:

```bash theme={null}
#!/usr/bin/env bash
# .mux/tool_post - runs after every tool
set -euo pipefail

[[ "$MUX_TOOL" == file_edit_* ]] || exit 0
file="${MUX_TOOL_INPUT_FILE_PATH:-}"
[[ -n "$file" ]] || exit 0

case "$file" in
  *.py)
    ruff check "$file"
    ;;
  *.ts|*.tsx)
    npx tsc --noEmit "$file"
    ;;
esac
```

```bash theme={null}
chmod +x .mux/tool_post
```

<details>
  <summary>Minimal formatter example (Go)</summary>

  ```bash theme={null}
  #!/usr/bin/env bash
  # .mux/tool_post - runs after every tool
  set -euo pipefail

  [[ "$MUX_TOOL" == file_edit_* ]] || exit 0
  file="${MUX_TOOL_INPUT_FILE_PATH:-}"
  [[ "$file" == *.go ]] || exit 0

  gofmt -w "$file"
  ```
</details>

Lint errors appear in `hook_output` and the agent can fix them.

<Note>
  `hook_output` is only shown in the UI when the hook produces output. For a cleaner experience,
  only print output when the hook has an effect—e.g., skip "Formatted: file" messages if the file
  was already formatted.
</Note>

***

## Set up environment

Create `.mux/tool_env` to configure your shell environment. This file is **sourced** before every `bash` tool call:

```bash theme={null}
# .mux/tool_env - sourced before bash commands

# direnv
eval "$(direnv export bash 2>/dev/null)" || true

# nvm
# export NVM_DIR="$HOME/.nvm"
# [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"

# Python virtualenv
# source .venv/bin/activate 2>/dev/null || true
```

<Note>
  Unlike hooks, `tool_env` doesn't need to be executable—it's sourced, not run. It only affects
  `bash` tools.
</Note>

***

## Reference

<Accordion title="Environment Variables">
  All hooks receive these environment variables:

  | Variable              | Description                                                      |
  | --------------------- | ---------------------------------------------------------------- |
  | `MUX_TOOL`            | Tool name: `bash`, `file_edit_replace_string`, `file_read`, etc. |
  | `MUX_WORKSPACE_ID`    | Current workspace identifier                                     |
  | `MUX_TOOL_INPUT_PATH` | Path to file containing full tool input (always set)             |

  Mux flattens the tool input into `MUX_TOOL_INPUT_<...>` environment variables (see the appendix below). Fields longer than 8KB are omitted—use `MUX_TOOL_INPUT_PATH` for full access.

  **Post-hook only (`tool_post`):**

  | Variable               | Description                              |
  | ---------------------- | ---------------------------------------- |
  | `MUX_TOOL_RESULT_PATH` | Path to file containing full tool result |

  Flattened result fields are available as `MUX_TOOL_RESULT_<...>`. Fields longer than 8KB are omitted—use `MUX_TOOL_RESULT_PATH` for full access.
</Accordion>

<Accordion title="Exit Codes">
  | Exit Code | `tool_pre` behavior                | `tool_post` behavior                  |
  | --------- | ---------------------------------- | ------------------------------------- |
  | `0`       | Tool executes normally             | Success, output shown to agent        |
  | Non-zero  | Tool blocked, error shown to agent | Failure, error shown in `hook_output` |
</Accordion>

<Accordion title="Hook Priority & Location">
  Mux searches for each hook file in this order:

  1. Project-level: `.mux/<hook>`
  2. User-level: `~/.mux/<hook>`

  This applies to `tool_pre`, `tool_post`, and `tool_env`.

  For SSH workspaces, hooks execute **on the remote machine**.
</Accordion>

<Accordion title="Timeouts">
  Hooks must complete within **10 seconds** or they're terminated. Long-running tools (builds, tests) don't count against this—only hook execution time.

  Keep hooks fast—if you need longer operations, consider running them asynchronously or in the background.
</Accordion>

<Accordion title="Comparison">
  | Feature        | `.mux/tool_pre`          | `.mux/tool_post`      | `.mux/tool_env`         |
  | -------------- | ------------------------ | --------------------- | ----------------------- |
  | **Purpose**    | Block dangerous commands | Lint/validate results | Environment setup       |
  | **Runs**       | Before tool              | After tool            | Sourced in bash shell   |
  | **Applies to** | All tools                | All tools             | `bash` tool only        |
  | **Use case**   | Block force-push         | Run ruff/eslint       | direnv, nvm, virtualenv |
</Accordion>

<Accordion title="Appendix: Tool input env vars (auto-generated)">
  Mux also provides flattened tool input env vars so hook scripts can stay compact.

  * Scalars become `MUX_TOOL_INPUT_<FIELD>`
  * Nested objects become `MUX_TOOL_INPUT_<PARENT>_<CHILD>`
  * Arrays also include `..._COUNT` and per-index variables like `..._<INDEX>`

  If a value is too large for the environment, it may be omitted (not set). Mux also caps the number of flattened env vars and array elements to keep hook execution reliable.

  <details>
    <summary>advisor (2)</summary>

    | Env var                       | JSON path      | Type   | Description |
    | ----------------------------- | -------------- | ------ | ----------- |
    | `MUX_TOOL_INPUT_ADVISOR_NAME` | `advisor_name` | string | —           |
    | `MUX_TOOL_INPUT_QUESTION`     | `question`     | string | —           |
  </details>

  <details>
    <summary>agent\_report (2)</summary>

    | Env var                          | JSON path        | Type   | Description |
    | -------------------------------- | ---------------- | ------ | ----------- |
    | `MUX_TOOL_INPUT_REPORT_MARKDOWN` | `reportMarkdown` | string | —           |
    | `MUX_TOOL_INPUT_TITLE`           | `title`          | string | —           |
  </details>

  <details>
    <summary>agent\_skill\_delete (4)</summary>

    | Env var                    | JSON path  | Type    | Description                                                                                                        |
    | -------------------------- | ---------- | ------- | ------------------------------------------------------------------------------------------------------------------ |
    | `MUX_TOOL_INPUT_CONFIRM`   | `confirm`  | boolean | Must be true to confirm deletion                                                                                   |
    | `MUX_TOOL_INPUT_FILE_PATH` | `filePath` | string  | Relative file path within the skill directory to delete. Required when target is 'file'                            |
    | `MUX_TOOL_INPUT_NAME`      | `name`     | string  | Skill name to delete                                                                                               |
    | `MUX_TOOL_INPUT_TARGET`    | `target`   | enum    | Deletion target: 'file' to delete a specific file, 'skill' to remove the entire skill directory (defaults to file) |
  </details>

  <details>
    <summary>agent\_skill\_list (1)</summary>

    | Env var                               | JSON path             | Type    | Description                                      |
    | ------------------------------------- | --------------------- | ------- | ------------------------------------------------ |
    | `MUX_TOOL_INPUT_INCLUDE_UNADVERTISED` | `includeUnadvertised` | boolean | When true, includes skills with advertise: false |
  </details>

  <details>
    <summary>agent\_skill\_read (1)</summary>

    | Env var               | JSON path | Type   | Description                                       |
    | --------------------- | --------- | ------ | ------------------------------------------------- |
    | `MUX_TOOL_INPUT_NAME` | `name`    | string | Skill name (directory name under the skills root) |
  </details>

  <details>
    <summary>agent\_skill\_read\_file (4)</summary>

    | Env var                    | JSON path  | Type   | Description                                                                    |
    | -------------------------- | ---------- | ------ | ------------------------------------------------------------------------------ |
    | `MUX_TOOL_INPUT_FILE_PATH` | `filePath` | string | Path to the file within the skill directory (relative)                         |
    | `MUX_TOOL_INPUT_LIMIT`     | `limit`    | number | Number of lines to return from offset (optional, returns all if not specified) |
    | `MUX_TOOL_INPUT_NAME`      | `name`     | string | Skill name (directory name under the skills root)                              |
    | `MUX_TOOL_INPUT_OFFSET`    | `offset`   | number | 1-based starting line number (optional, defaults to 1)                         |
  </details>

  <details>
    <summary>agent\_skill\_write (3)</summary>

    | Env var                    | JSON path  | Type   | Description                                                |
    | -------------------------- | ---------- | ------ | ---------------------------------------------------------- |
    | `MUX_TOOL_INPUT_CONTENT`   | `content`  | string | File content to write                                      |
    | `MUX_TOOL_INPUT_FILE_PATH` | `filePath` | string | Relative path within skill directory. Defaults to SKILL.md |
    | `MUX_TOOL_INPUT_NAME`      | `name`     | string | Skill name (directory name under the global skills root)   |
  </details>

  <details>
    <summary>analytics\_query (6)</summary>

    | Env var                         | JSON path         | Type   | Description                                                                          |
    | ------------------------------- | ----------------- | ------ | ------------------------------------------------------------------------------------ |
    | `MUX_TOOL_INPUT_SQL`            | `sql`             | string | DuckDB SQL query to execute                                                          |
    | `MUX_TOOL_INPUT_TITLE`          | `title`           | string | Optional chart title                                                                 |
    | `MUX_TOOL_INPUT_VISUALIZATION`  | `visualization`   | enum   | Optional visualization type for rendering the query result                           |
    | `MUX_TOOL_INPUT_X_AXIS`         | `x_axis`          | string | Optional column name for the visualization X axis                                    |
    | `MUX_TOOL_INPUT_Y_AXIS_<INDEX>` | `y_axis[<INDEX>]` | string | Optional column name(s) for the visualization Y axis                                 |
    | `MUX_TOOL_INPUT_Y_AXIS_COUNT`   | `y_axis.length`   | number | Number of elements in y\_axis (Optional column name(s) for the visualization Y axis) |
  </details>

  <details>
    <summary>ask\_user\_question (8)</summary>

    | Env var                                                        | JSON path                                         | Type    | Description                                        |
    | -------------------------------------------------------------- | ------------------------------------------------- | ------- | -------------------------------------------------- |
    | `MUX_TOOL_INPUT_ANSWERS_<KEY>`                                 | `answers[<KEY>]`                                  | string  | —                                                  |
    | `MUX_TOOL_INPUT_QUESTIONS_<INDEX>_HEADER`                      | `questions[<INDEX>].header`                       | string  | Short label shown in the UI (keep it concise)      |
    | `MUX_TOOL_INPUT_QUESTIONS_<INDEX>_MULTI_SELECT`                | `questions[<INDEX>].multiSelect`                  | boolean | —                                                  |
    | `MUX_TOOL_INPUT_QUESTIONS_<INDEX>_OPTIONS_<INDEX>_DESCRIPTION` | `questions[<INDEX>].options[<INDEX>].description` | string  | —                                                  |
    | `MUX_TOOL_INPUT_QUESTIONS_<INDEX>_OPTIONS_<INDEX>_LABEL`       | `questions[<INDEX>].options[<INDEX>].label`       | string  | —                                                  |
    | `MUX_TOOL_INPUT_QUESTIONS_<INDEX>_OPTIONS_COUNT`               | `questions[<INDEX>].options.length`               | number  | Number of elements in questions\[\<INDEX>].options |
    | `MUX_TOOL_INPUT_QUESTIONS_<INDEX>_QUESTION`                    | `questions[<INDEX>].question`                     | string  | —                                                  |
    | `MUX_TOOL_INPUT_QUESTIONS_COUNT`                               | `questions.length`                                | number  | Number of elements in questions                    |
  </details>

  <details>
    <summary>attach\_file (3)</summary>

    | Env var                     | JSON path   | Type   | Description                                                            |
    | --------------------------- | ----------- | ------ | ---------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_FILENAME`   | `filename`  | string | Optional filename override to present to the model.                    |
    | `MUX_TOOL_INPUT_MEDIA_TYPE` | `mediaType` | string | Optional media type override when the filename/extension is ambiguous. |
    | `MUX_TOOL_INPUT_PATH`       | `path`      | string | The path to the file to attach (absolute or relative)                  |
  </details>

  <details>
    <summary>bash (5)</summary>

    | Env var                            | JSON path           | Type    | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
    | ---------------------------------- | ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_DISPLAY_NAME`      | `display_name`      | string  | Human-readable name for the process (e.g., 'Dev Server', 'TypeCheck Watch'). Required for all bash invocations since any process can be sent to background.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
    | `MUX_TOOL_INPUT_MODEL_INTENT`      | `model_intent`      | string  | Optional. Short user-facing purpose for this command, shown next to the command in collapsed chat. Use a present-participle phrase in plain English, under 100 characters. Do not repeat the command or include duration, because Mux appends those. Examples: 'Running the unit tests', 'Checking repository state', 'Inspecting build output'.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
    | `MUX_TOOL_INPUT_RUN_IN_BACKGROUND` | `run_in_background` | boolean | Run this command in the background without blocking. Use for processes running >5s (dev servers, builds, file watchers). Do NOT use for quick commands (\<5s), interactive processes (no stdin support), or processes requiring real-time output (use foreground with larger timeout instead). Returns immediately with a taskId (bash:\<processId>) and backgroundProcessId. Read output with task\_await (returns only new output since last check). Terminate with task\_terminate using the taskId. List active tasks with task\_list. Process persists until timeout\_secs expires, terminated, or workspace is removed. For long-running tasks like builds or compilations, prefer background mode to continue productive work in parallel. Do not call task\_await in the same parallel tool-call batch; wait for the returned taskId first. When you actually need the output, read it with task\_await; do not poll task\_await just because the process is still running. |
    | `MUX_TOOL_INPUT_SCRIPT`            | `script`            | string  | The bash script/command to execute                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
    | `MUX_TOOL_INPUT_TIMEOUT_SECS`      | `timeout_secs`      | number  | Timeout in seconds. For foreground: max execution time before kill. For background: max lifetime before auto-termination. Start small and increase on retry; avoid large initial values to keep UX responsive                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
  </details>

  <details>
    <summary>bash\_background\_terminate (1)</summary>

    | Env var                     | JSON path    | Type   | Description                        |
    | --------------------------- | ------------ | ------ | ---------------------------------- |
    | `MUX_TOOL_INPUT_PROCESS_ID` | `process_id` | string | Background process ID to terminate |
  </details>

  <details>
    <summary>bash\_output (4)</summary>

    | Env var                         | JSON path        | Type    | Description                                                                                                                                                                                                                                                                                                                                                                                                     |
    | ------------------------------- | ---------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_FILTER`         | `filter`         | string  | Optional regex to filter output lines. By default, only matching lines are returned. When filter\_exclude is true, matching lines are excluded instead. Non-matching lines are permanently discarded and cannot be retrieved later.                                                                                                                                                                             |
    | `MUX_TOOL_INPUT_FILTER_EXCLUDE` | `filter_exclude` | boolean | When true, lines matching 'filter' are excluded instead of kept. Key behavior: excluded lines do NOT cause early return from timeout - waiting continues until non-excluded output arrives or process exits. Use to avoid busy polling on progress spam (e.g., filter='⏳\|waiting\|...' with filter\_exclude=true lets you set a long timeout and only wake on meaningful output). Requires 'filter' to be set. |
    | `MUX_TOOL_INPUT_PROCESS_ID`     | `process_id`     | string  | The ID of the background process to retrieve output from                                                                                                                                                                                                                                                                                                                                                        |
    | `MUX_TOOL_INPUT_TIMEOUT_SECS`   | `timeout_secs`   | number  | Seconds to wait for new output. If no output is immediately available and process is still running, blocks up to this duration. Returns early when output arrives or process exits. Only use long timeouts (>15s) when no other useful work can be done in parallel.                                                                                                                                            |
  </details>

  <details>
    <summary>code\_execution (1)</summary>

    | Env var               | JSON path | Type   | Description                                   |
    | --------------------- | --------- | ------ | --------------------------------------------- |
    | `MUX_TOOL_INPUT_CODE` | `code`    | string | JavaScript code to execute in the PTC sandbox |
  </details>

  <details>
    <summary>complete\_goal (2)</summary>

    | Env var                  | JSON path | Type   | Description                                                                                                                                                                                          |
    | ------------------------ | --------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_GOAL_ID` | `goalId`  | string | Optional optimistic-concurrency token. Pass the `goalId` returned by `get_goal` to ensure the completion is rejected with a typed conflict error if the user clears or replaces the goal mid-stream. |
    | `MUX_TOOL_INPUT_SUMMARY` | `summary` | string | Required 1-2 sentence justification for completing the current goal.                                                                                                                                 |
  </details>

  <details>
    <summary>desktop\_click (3)</summary>

    | Env var                 | JSON path | Type   | Description                                       |
    | ----------------------- | --------- | ------ | ------------------------------------------------- |
    | `MUX_TOOL_INPUT_BUTTON` | `button`  | enum   | Optional mouse button to click. Defaults to left. |
    | `MUX_TOOL_INPUT_X`      | `x`       | number | Target X coordinate in screen pixels.             |
    | `MUX_TOOL_INPUT_Y`      | `y`       | number | Target Y coordinate in screen pixels.             |
  </details>

  <details>
    <summary>desktop\_double\_click (3)</summary>

    | Env var                 | JSON path | Type   | Description                                              |
    | ----------------------- | --------- | ------ | -------------------------------------------------------- |
    | `MUX_TOOL_INPUT_BUTTON` | `button`  | enum   | Optional mouse button to double-click. Defaults to left. |
    | `MUX_TOOL_INPUT_X`      | `x`       | number | Target X coordinate in screen pixels.                    |
    | `MUX_TOOL_INPUT_Y`      | `y`       | number | Target Y coordinate in screen pixels.                    |
  </details>

  <details>
    <summary>desktop\_drag (4)</summary>

    | Env var                  | JSON path | Type   | Description                             |
    | ------------------------ | --------- | ------ | --------------------------------------- |
    | `MUX_TOOL_INPUT_END_X`   | `endX`    | number | Ending X coordinate in screen pixels.   |
    | `MUX_TOOL_INPUT_END_Y`   | `endY`    | number | Ending Y coordinate in screen pixels.   |
    | `MUX_TOOL_INPUT_START_X` | `startX`  | number | Starting X coordinate in screen pixels. |
    | `MUX_TOOL_INPUT_START_Y` | `startY`  | number | Starting Y coordinate in screen pixels. |
  </details>

  <details>
    <summary>desktop\_key\_press (1)</summary>

    | Env var              | JSON path | Type   | Description                                     |
    | -------------------- | --------- | ------ | ----------------------------------------------- |
    | `MUX_TOOL_INPUT_KEY` | `key`     | string | Key or key combination to press on the desktop. |
  </details>

  <details>
    <summary>desktop\_move\_mouse (2)</summary>

    | Env var            | JSON path | Type   | Description                           |
    | ------------------ | --------- | ------ | ------------------------------------- |
    | `MUX_TOOL_INPUT_X` | `x`       | number | Target X coordinate in screen pixels. |
    | `MUX_TOOL_INPUT_Y` | `y`       | number | Target Y coordinate in screen pixels. |
  </details>

  <details>
    <summary>desktop\_screenshot (2)</summary>

    | Env var                        | JSON path      | Type   | Description                                                     |
    | ------------------------------ | -------------- | ------ | --------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_SCALED_HEIGHT` | `scaledHeight` | number | Optional scaled height hint in pixels for downstream consumers. |
    | `MUX_TOOL_INPUT_SCALED_WIDTH`  | `scaledWidth`  | number | Optional scaled width hint in pixels for downstream consumers.  |
  </details>

  <details>
    <summary>desktop\_scroll (4)</summary>

    | Env var                  | JSON path | Type   | Description                                 |
    | ------------------------ | --------- | ------ | ------------------------------------------- |
    | `MUX_TOOL_INPUT_DELTA_X` | `deltaX`  | number | Optional horizontal scroll delta in pixels. |
    | `MUX_TOOL_INPUT_DELTA_Y` | `deltaY`  | number | Vertical scroll delta in pixels.            |
    | `MUX_TOOL_INPUT_X`       | `x`       | number | Target X coordinate in screen pixels.       |
    | `MUX_TOOL_INPUT_Y`       | `y`       | number | Target Y coordinate in screen pixels.       |
  </details>

  <details>
    <summary>desktop\_type (1)</summary>

    | Env var               | JSON path | Type   | Description                                  |
    | --------------------- | --------- | ------ | -------------------------------------------- |
    | `MUX_TOOL_INPUT_TEXT` | `text`    | string | Text to type into the active desktop target. |
  </details>

  <details>
    <summary>file\_edit\_insert (4)</summary>

    | Env var                        | JSON path       | Type   | Description                                                                             |
    | ------------------------------ | --------------- | ------ | --------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_CONTENT`       | `content`       | string | The content to insert                                                                   |
    | `MUX_TOOL_INPUT_INSERT_AFTER`  | `insert_after`  | string | Anchor text to insert after. Content will be placed immediately after this substring.   |
    | `MUX_TOOL_INPUT_INSERT_BEFORE` | `insert_before` | string | Anchor text to insert before. Content will be placed immediately before this substring. |
    | `MUX_TOOL_INPUT_PATH`          | `path`          | string | Path to the file to edit (absolute or relative to the current workspace)                |
  </details>

  <details>
    <summary>file\_edit\_replace\_lines (7)</summary>

    | Env var                                 | JSON path                 | Type   | Description                                                                                                                                |
    | --------------------------------------- | ------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
    | `MUX_TOOL_INPUT_END_LINE`               | `end_line`                | number | 1-indexed end line (inclusive) to replace                                                                                                  |
    | `MUX_TOOL_INPUT_EXPECTED_LINES_<INDEX>` | `expected_lines[<INDEX>]` | string | Optional safety check. When provided, the current lines in the specified range must match exactly.                                         |
    | `MUX_TOOL_INPUT_EXPECTED_LINES_COUNT`   | `expected_lines.length`   | number | Number of elements in expected\_lines (Optional safety check. When provided, the current lines in the specified range must match exactly.) |
    | `MUX_TOOL_INPUT_NEW_LINES_<INDEX>`      | `new_lines[<INDEX>]`      | string | Replacement lines. Provide an empty array to delete the specified range.                                                                   |
    | `MUX_TOOL_INPUT_NEW_LINES_COUNT`        | `new_lines.length`        | number | Number of elements in new\_lines (Replacement lines. Provide an empty array to delete the specified range.)                                |
    | `MUX_TOOL_INPUT_PATH`                   | `path`                    | string | Path to the file to edit (absolute or relative to the current workspace)                                                                   |
    | `MUX_TOOL_INPUT_START_LINE`             | `start_line`              | number | 1-indexed start line (inclusive) to replace                                                                                                |
  </details>

  <details>
    <summary>file\_edit\_replace\_string (4)</summary>

    | Env var                        | JSON path       | Type   | Description                                                                                                                                           |
    | ------------------------------ | --------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_NEW_STRING`    | `new_string`    | string | The replacement text                                                                                                                                  |
    | `MUX_TOOL_INPUT_OLD_STRING`    | `old_string`    | string | The exact text to replace (must be unique in file if replace\_count is 1). Include enough context (indentation, surrounding lines) to make it unique. |
    | `MUX_TOOL_INPUT_PATH`          | `path`          | string | Path to the file to edit (absolute or relative to the current workspace)                                                                              |
    | `MUX_TOOL_INPUT_REPLACE_COUNT` | `replace_count` | number | Number of occurrences to replace (default: 1). Use -1 to replace all occurrences. If 1, old\_string must be unique in the file.                       |
  </details>

  <details>
    <summary>file\_read (3)</summary>

    | Env var                 | JSON path | Type   | Description                                                                    |
    | ----------------------- | --------- | ------ | ------------------------------------------------------------------------------ |
    | `MUX_TOOL_INPUT_LIMIT`  | `limit`   | number | Number of lines to return from offset (optional, returns all if not specified) |
    | `MUX_TOOL_INPUT_OFFSET` | `offset`  | number | 1-based starting line number (optional, defaults to 1)                         |
    | `MUX_TOOL_INPUT_PATH`   | `path`    | string | The path to the file to read (absolute or relative)                            |
  </details>

  <details>
    <summary>image\_edit (5)</summary>

    | Env var                        | JSON path      | Type   | Description                                                                                                                           |
    | ------------------------------ | -------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_N`             | `n`            | number | Number of edited variants to create. Defaults to 1; request multiple variants only when the user asks or variants are clearly useful. |
    | `MUX_TOOL_INPUT_OUTPUT_FORMAT` | `outputFormat` | enum   | Optional output format. Defaults to png.                                                                                              |
    | `MUX_TOOL_INPUT_PROMPT`        | `prompt`       | string | Edit prompt describing the desired image changes                                                                                      |
    | `MUX_TOOL_INPUT_QUALITY`       | `quality`      | enum   | Optional edit quality. Defaults to the provider/model default.                                                                        |
    | `MUX_TOOL_INPUT_SOURCE_PATH`   | `sourcePath`   | string | Path to the existing source image to edit                                                                                             |
  </details>

  <details>
    <summary>image\_generate (4)</summary>

    | Env var                        | JSON path      | Type   | Description                                                                                                |
    | ------------------------------ | -------------- | ------ | ---------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_N`             | `n`            | number | Number of images to generate. Defaults to 1 and must not exceed the user's configured Image Tools maximum. |
    | `MUX_TOOL_INPUT_OUTPUT_FORMAT` | `outputFormat` | enum   | Optional output format. Defaults to png.                                                                   |
    | `MUX_TOOL_INPUT_PROMPT`        | `prompt`       | string | Prompt describing the image(s) to generate                                                                 |
    | `MUX_TOOL_INPUT_QUALITY`       | `quality`      | enum   | Optional generation quality. Defaults to the provider/model default.                                       |
  </details>

  <details>
    <summary>mux\_agents\_write (2)</summary>

    | Env var                      | JSON path    | Type    | Description                                                                            |
    | ---------------------------- | ------------ | ------- | -------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_CONFIRM`     | `confirm`    | boolean | Must be true to apply the write. The agent should ask the user for confirmation first. |
    | `MUX_TOOL_INPUT_NEW_CONTENT` | `newContent` | string  | The full new contents of the AGENTS.md file                                            |
  </details>

  <details>
    <summary>mux\_config\_read (3)</summary>

    | Env var                       | JSON path       | Type   | Description                                                                                                               |
    | ----------------------------- | --------------- | ------ | ------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_FILE`         | `file`          | enum   | Which configuration file to read                                                                                          |
    | `MUX_TOOL_INPUT_PATH_<INDEX>` | `path[<INDEX>]` | string | Optional path segments to read a specific nested value. If omitted, returns the full config.                              |
    | `MUX_TOOL_INPUT_PATH_COUNT`   | `path.length`   | number | Number of elements in path (Optional path segments to read a specific nested value. If omitted, returns the full config.) |
  </details>

  <details>
    <summary>mux\_config\_write (7)</summary>

    | Env var                                          | JSON path                           | Type    | Description                                                                   |
    | ------------------------------------------------ | ----------------------------------- | ------- | ----------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_CONFIRM`                         | `confirm`                           | boolean | Must be true to apply the write. Ask the user for confirmation first.         |
    | `MUX_TOOL_INPUT_FILE`                            | `file`                              | enum    | Which configuration file to write                                             |
    | `MUX_TOOL_INPUT_OPERATIONS_<INDEX>_OP`           | `operations[<INDEX>].op`            | literal | —                                                                             |
    | `MUX_TOOL_INPUT_OPERATIONS_<INDEX>_PATH_<INDEX>` | `operations[<INDEX>].path[<INDEX>]` | string  | —                                                                             |
    | `MUX_TOOL_INPUT_OPERATIONS_<INDEX>_PATH_COUNT`   | `operations[<INDEX>].path.length`   | number  | Number of elements in operations\[\<INDEX>].path                              |
    | `MUX_TOOL_INPUT_OPERATIONS_<INDEX>_VALUE`        | `operations[<INDEX>].value`         | unknown | —                                                                             |
    | `MUX_TOOL_INPUT_OPERATIONS_COUNT`                | `operations.length`                 | number  | Number of elements in operations (Operations to apply to the config document) |
  </details>

  <details>
    <summary>notify (2)</summary>

    | Env var                  | JSON path | Type   | Description                                                                                                 |
    | ------------------------ | --------- | ------ | ----------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_MESSAGE` | `message` | string | Optional notification body with more details (max 200 chars). Keep it brief - users may only see a preview. |
    | `MUX_TOOL_INPUT_TITLE`   | `title`   | string | Short notification title (max 64 chars). Should be concise and actionable.                                  |
  </details>

  <details>
    <summary>review\_pane\_update (4)</summary>

    | Env var                                | JSON path                | Type   | Description                                                                                                                                       |
    | -------------------------------------- | ------------------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_HUNKS_<INDEX>_COMMENT` | `hunks[<INDEX>].comment` | string | Short note (\~1 sentence) telling the user what to look at and why.                                                                               |
    | `MUX_TOOL_INPUT_HUNKS_<INDEX>_PATH`    | `hunks[<INDEX>].path`    | string | Filter in `path[:range]` form, e.g. "src/foo.ts" or "src/foo.ts:42-58". Path is workspace-relative; range uses new-file line numbers (inclusive). |
    | `MUX_TOOL_INPUT_HUNKS_COUNT`           | `hunks.length`           | number | Number of elements in hunks (List of hunks to flag for review.)                                                                                   |
    | `MUX_TOOL_INPUT_OPERATION`             | `operation`              | enum   | 'replace' overwrites the assisted set; 'add' appends to it.                                                                                       |
  </details>

  <details>
    <summary>skills\_catalog\_read (3)</summary>

    | Env var                   | JSON path | Type   | Description                                                         |
    | ------------------------- | --------- | ------ | ------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_OWNER`    | `owner`   | string | GitHub owner from the search result (e.g. 'vercel-labs')            |
    | `MUX_TOOL_INPUT_REPO`     | `repo`    | string | GitHub repository name from the search result (e.g. 'agent-skills') |
    | `MUX_TOOL_INPUT_SKILL_ID` | `skillId` | string | Skill ID from the search result                                     |
  </details>

  <details>
    <summary>skills\_catalog\_search (2)</summary>

    | Env var                | JSON path | Type   | Description                                       |
    | ---------------------- | --------- | ------ | ------------------------------------------------- |
    | `MUX_TOOL_INPUT_LIMIT` | `limit`   | number | Maximum number of results to return (default: 10) |
    | `MUX_TOOL_INPUT_QUERY` | `query`   | string | Search query to find skills in the catalog        |
  </details>

  <details>
    <summary>switch\_agent (3)</summary>

    | Env var                    | JSON path  | Type   | Description |
    | -------------------------- | ---------- | ------ | ----------- |
    | `MUX_TOOL_INPUT_AGENT_ID`  | `agentId`  | string | —           |
    | `MUX_TOOL_INPUT_FOLLOW_UP` | `followUp` | string | —           |
    | `MUX_TOOL_INPUT_REASON`    | `reason`   | string | —           |
  </details>

  <details>
    <summary>task (8)</summary>

    | Env var                            | JSON path           | Type    | Description                                                                                                                                                                                                                                                                                                                                                                   |
    | ---------------------------------- | ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_AGENT_ID`          | `agentId`           | string  | —                                                                                                                                                                                                                                                                                                                                                                             |
    | `MUX_TOOL_INPUT_N`                 | `n`                 | number  | Optional best-of count. Use n when several agents should try the same prompt independently. Mutually exclusive with variants; omit both for a single task. Only use grouped runs for sub-agents without interfering side effects, such as read-only agents like explore.                                                                                                      |
    | `MUX_TOOL_INPUT_PROMPT`            | `prompt`            | string  | —                                                                                                                                                                                                                                                                                                                                                                             |
    | `MUX_TOOL_INPUT_RUN_IN_BACKGROUND` | `run_in_background` | boolean | —                                                                                                                                                                                                                                                                                                                                                                             |
    | `MUX_TOOL_INPUT_SUBAGENT_TYPE`     | `subagent_type`     | string  | —                                                                                                                                                                                                                                                                                                                                                                             |
    | `MUX_TOOL_INPUT_TITLE`             | `title`             | string  | —                                                                                                                                                                                                                                                                                                                                                                             |
    | `MUX_TOOL_INPUT_VARIANTS_<INDEX>`  | `variants[<INDEX>]` | string  | Optional labels for sibling runs of the same prompt template. Use variants when the task should be repeated across labeled lanes such as issue numbers, commit windows, or frontend/backend/tests/docs review lanes. Mutually exclusive with n. When provided, Mux launches one sibling per label and substitutes \${variant} in the prompt.                                  |
    | `MUX_TOOL_INPUT_VARIANTS_COUNT`    | `variants.length`   | number  | Number of elements in variants (Optional labels for sibling runs of the same prompt template. Use variants when the task should be repeated across labeled lanes such as issue numbers, commit windows, or frontend/backend/tests/docs review lanes. Mutually exclusive with n. When provided, Mux launches one sibling per label and substitutes \${variant} in the prompt.) |
  </details>

  <details>
    <summary>task\_apply\_git\_patch (5)</summary>

    | Env var                       | JSON path      | Type    | Description                                                                                                                    |
    | ----------------------------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------ |
    | `MUX_TOOL_INPUT_DRY_RUN`      | `dry_run`      | boolean | When true, attempt to apply the patch in a temporary git worktree and then discard it (does not modify the current workspace). |
    | `MUX_TOOL_INPUT_FORCE`        | `force`        | boolean | When true, allow apply even if the patch was previously applied (and skip clean-tree checks).                                  |
    | `MUX_TOOL_INPUT_PROJECT_PATH` | `project_path` | string  | When provided, apply only the patch artifact for this project path.                                                            |
    | `MUX_TOOL_INPUT_TASK_ID`      | `task_id`      | string  | Child task ID whose patch artifact should be applied                                                                           |
    | `MUX_TOOL_INPUT_THREE_WAY`    | `three_way`    | boolean | When true, run git am with --3way                                                                                              |
  </details>

  <details>
    <summary>task\_await (5)</summary>

    | Env var                           | JSON path           | Type    | Description                                                                                                                                                                                                                                                                                                   |
    | --------------------------------- | ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_FILTER`           | `filter`            | string  | Optional regex to filter bash task output lines. By default, only matching lines are returned. When filter\_exclude is true, matching lines are excluded instead. Non-matching lines are discarded and cannot be retrieved later.                                                                             |
    | `MUX_TOOL_INPUT_FILTER_EXCLUDE`   | `filter_exclude`    | boolean | When true, lines matching 'filter' are excluded instead of kept. Requires 'filter' to be set.                                                                                                                                                                                                                 |
    | `MUX_TOOL_INPUT_TASK_IDS_<INDEX>` | `task_ids[<INDEX>]` | string  | List of task IDs to await — use only real IDs returned by prior task, bash, or task\_list tool results; never fabricate an ID. When omitted, waits for all active descendant tasks of the current workspace.                                                                                                  |
    | `MUX_TOOL_INPUT_TASK_IDS_COUNT`   | `task_ids.length`   | number  | Number of elements in task\_ids (List of task IDs to await — use only real IDs returned by prior task, bash, or task\_list tool results; never fabricate an ID. When omitted, waits for all active descendant tasks of the current workspace.)                                                                |
    | `MUX_TOOL_INPUT_TIMEOUT_SECS`     | `timeout_secs`      | number  | Maximum time to wait in seconds for each task. For bash tasks, this waits for NEW output (or process exit). If exceeded, the result returns status=queued\|running\|awaiting\_report (task is still active). Defaults to 600 seconds (10 minutes) if not specified. Set to 0 for a non-blocking status check. |
  </details>

  <details>
    <summary>task\_list (2)</summary>

    | Env var                           | JSON path           | Type   | Description                                                                                                             |
    | --------------------------------- | ------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_STATUSES_<INDEX>` | `statuses[<INDEX>]` | enum   | Task statuses to include. Defaults to active tasks: queued, running, awaiting\_report.                                  |
    | `MUX_TOOL_INPUT_STATUSES_COUNT`   | `statuses.length`   | number | Number of elements in statuses (Task statuses to include. Defaults to active tasks: queued, running, awaiting\_report.) |
  </details>

  <details>
    <summary>task\_terminate (2)</summary>

    | Env var                           | JSON path           | Type   | Description                                                                                                                         |
    | --------------------------------- | ------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_TASK_IDS_<INDEX>` | `task_ids[<INDEX>]` | string | List of task IDs to terminate. Each must be a descendant sub-agent task of the current workspace.                                   |
    | `MUX_TOOL_INPUT_TASK_IDS_COUNT`   | `task_ids.length`   | number | Number of elements in task\_ids (List of task IDs to terminate. Each must be a descendant sub-agent task of the current workspace.) |
  </details>

  <details>
    <summary>todo\_write (3)</summary>

    | Env var                                | JSON path                | Type   | Description                                                                                                                   |
    | -------------------------------------- | ------------------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------- |
    | `MUX_TOOL_INPUT_TODOS_<INDEX>_CONTENT` | `todos[<INDEX>].content` | string | Task description with tense matching status: past for completed, present progressive for in\_progress, imperative for pending |
    | `MUX_TOOL_INPUT_TODOS_<INDEX>_STATUS`  | `todos[<INDEX>].status`  | enum   | Task status                                                                                                                   |
    | `MUX_TOOL_INPUT_TODOS_COUNT`           | `todos.length`           | number | Number of elements in todos                                                                                                   |
  </details>

  <details>
    <summary>web\_fetch (1)</summary>

    | Env var              | JSON path | Type   | Description                      |
    | -------------------- | --------- | ------ | -------------------------------- |
    | `MUX_TOOL_INPUT_URL` | `url`     | string | The URL to fetch (http or https) |
  </details>
</Accordion>

***

## More examples

<Accordion title="Format files after edits">
  ```bash theme={null}
  #!/usr/bin/env bash
  # .mux/tool_post

  if [[ "$MUX_TOOL" == file_edit_* ]]; then
    file="$MUX_TOOL_INPUT_FILE_PATH"
    prettier --write --log-level silent "$file" 2>/dev/null || true
  fi
  ```
</Accordion>

<Accordion title="Log tool execution times">
  ```bash theme={null}
  #!/usr/bin/env bash
  # .mux/tool_post

  # Tool results are available via MUX_TOOL_RESULT_* if needed.
  echo "$(date '+%H:%M:%S') $MUX_TOOL completed" >> /tmp/mux-tools.log
  ```
</Accordion>

<Accordion title="Python hook">
  ```python theme={null}
  #!/usr/bin/env python3
  # .mux/tool_pre

  import os, sys

  tool = os.environ.get('MUX_TOOL', '')
  script = os.environ.get('MUX_TOOL_INPUT_SCRIPT', '')

  if tool == 'bash':
      if 'rm -rf /' in script:
          print("❌ Blocked dangerous command", file=sys.stderr)
          sys.exit(1)

  sys.exit(0)  # Allow
  ```
</Accordion>
