From 36ad1606ee18f5779bf2fd1c4f553ef5ae093aa5 Mon Sep 17 00:00:00 2001 From: Bryan Helmkamp Date: Sun, 8 Mar 2026 16:49:28 -0400 Subject: [PATCH] Update docs for tool-level hooks, server mode, and auto-PR - hooks.mdx: add pre_tool_use/post_tool_use/post_tool_use_failure events, tool-specific context fields, matcher support for tool names - cli.mdx: add --mode and --server-url flags to arc exec - run-configuration.mdx: add [pull_request] section - github.mdx: add auto-PR to features table Co-Authored-By: Claude Opus 4.6 --- .claude/skills/docs/watermark | 2 +- docs/agents/hooks.mdx | 38 +++++++++++++++++++++++++++- docs/execution/run-configuration.mdx | 16 ++++++++++++ docs/integrations/github.mdx | 1 + docs/reference/cli.mdx | 2 ++ 5 files changed, 57 insertions(+), 2 deletions(-) diff --git a/.claude/skills/docs/watermark b/.claude/skills/docs/watermark index e9c6aac13..1608de7cd 100644 --- a/.claude/skills/docs/watermark +++ b/.claude/skills/docs/watermark @@ -1 +1 @@ -d1b06dede14cbafec1d98c3c6d0817d456d9b081 +15c638832e7049a64067818b3c955df33fb35903 diff --git a/docs/agents/hooks.mdx b/docs/agents/hooks.mdx index 753de210a..1df694a3b 100644 --- a/docs/agents/hooks.mdx +++ b/docs/agents/hooks.mdx @@ -97,6 +97,9 @@ Each hook fires on a specific lifecycle event: | `sandbox_ready` | After the sandbox environment is created | No | | `sandbox_cleanup` | Before the sandbox is torn down | No | | `checkpoint_saved` | After a checkpoint is written to disk | No | +| `pre_tool_use` | Before an agent tool call executes | Yes | +| `post_tool_use` | After an agent tool call succeeds | No | +| `post_tool_use_failure` | After an agent tool call fails | No | ## Configuration @@ -128,7 +131,7 @@ sandbox = false Blocking hooks can affect workflow execution. Non-blocking hooks run for side effects only — their decisions are ignored. -**Blocking by default:** `run_start`, `stage_start`, `edge_selected`. These events represent decision points where a hook can prevent or redirect execution. +**Blocking by default:** `run_start`, `stage_start`, `edge_selected`, `pre_tool_use`. These events represent decision points where a hook can prevent or redirect execution. **Non-blocking by default:** All other events. Override with `blocking = true` if needed. @@ -188,6 +191,7 @@ The `matcher` field is a regex pattern that filters which stages trigger a hook. - The **node ID** (e.g., `"implement"`, `"test"`) - The **handler type** (e.g., `"agent"`, `"command"`, `"prompt"`) - The **edge source** and **edge target** (for `edge_selected` events) +- The **tool name** (for `pre_tool_use`, `post_tool_use`, `post_tool_use_failure` events) If any of these fields match the regex, the hook fires. If `matcher` is omitted, the hook fires for all stages of the specified event. @@ -254,6 +258,29 @@ The full event context is available as a JSON payload. For command hooks, it is Fields vary by event — `edge_from`/`edge_to`/`edge_label` are only set for `edge_selected`, `failure_reason` for failure events, `attempt`/`max_attempts` for `stage_retrying`, etc. Null fields are omitted from the serialized JSON. +For tool-level events (`pre_tool_use`, `post_tool_use`, `post_tool_use_failure`), the context includes additional fields: + +| Field | Events | Description | +|---|---|---| +| `tool_name` | All tool events | Name of the tool being called (e.g., `shell`, `write_file`) | +| `tool_input` | `pre_tool_use` | JSON object with the tool's input arguments | +| `tool_call_id` | `post_tool_use`, `post_tool_use_failure` | Unique identifier for the tool call | +| `tool_output` | `post_tool_use` | The tool's output string | +| `error_message` | `post_tool_use_failure` | The error message from the failed tool call | + + +```json +{ + "event": "pre_tool_use", + "run_id": "run-abc123", + "workflow_name": "ci-pipeline", + "node_id": "implement", + "tool_name": "shell", + "tool_input": {"command": "rm -rf /tmp/build"} +} +``` + + ## Timeouts Each hook type has a default timeout: @@ -324,4 +351,13 @@ model = "sonnet" max_tool_rounds = 20 blocking = true timeout_ms = 120000 + +# Auto-format Rust files after writes +[[hooks]] +name = "cargo-fmt" +event = "post_tool_use" +command = "cargo fmt" +matcher = "write_file" +blocking = false +sandbox = true ``` diff --git a/docs/execution/run-configuration.mdx b/docs/execution/run-configuration.mdx index b3924ebb6..7785fab18 100644 --- a/docs/execution/run-configuration.mdx +++ b/docs/execution/run-configuration.mdx @@ -76,6 +76,9 @@ exclude_globs = ["**/node_modules/**", "**/.cache/**"] repo_name = "arc" repo_url = "https://github.com/qltysh/arc" +[pull_request] +enabled = true + [[hooks]] event = "stage_start" command = "./scripts/pre-check.sh" @@ -234,6 +237,19 @@ digraph CI { If a `$variable` in the DOT file has no matching entry in `[vars]`, Arc raises an error immediately. A bare `$` not followed by an identifier (e.g. `costs $5`) is left as-is. +### `[pull_request]` + +Automatically open a GitHub pull request when the workflow run completes successfully. Requires a [GitHub App](/integrations/github) to be configured. + +```toml title="run.toml" +[pull_request] +enabled = true +``` + +| Field | Description | +|---|---| +| `enabled` | When `true`, Arc creates a PR from the agent's working branch after a successful run. Default: `false`. | + ### `[[hooks]]` Define hooks that run in response to lifecycle events. Each hook is a TOML array entry: diff --git a/docs/integrations/github.mdx b/docs/integrations/github.mdx index 6418a087c..9a204b4e3 100644 --- a/docs/integrations/github.mdx +++ b/docs/integrations/github.mdx @@ -12,6 +12,7 @@ Arc uses a [GitHub App](https://docs.github.com/en/apps/overview) to authenticat | **OAuth login** | Users sign in to the web UI with their GitHub account | | **Private repo cloning** | Daytona and Docker sandboxes clone private repositories using short-lived Installation Access Tokens | | **Checkpoint pushing** | After each workflow stage, Arc pushes the run branch and metadata branch back to origin from inside the sandbox | +| **Auto-PR** | When `[pull_request] enabled = true` in the [run config](/execution/run-configuration#pull_request), Arc opens a PR from the agent's working branch after a successful run | ## Setup diff --git a/docs/reference/cli.mdx b/docs/reference/cli.mdx index 118bd4d3b..7f6e45886 100644 --- a/docs/reference/cli.mdx +++ b/docs/reference/cli.mdx @@ -127,6 +127,8 @@ arc exec "Refactor the auth module" --permissions full --auto-approve | `--verbose` | Print full LLM request/response JSON to stderr | — | | `--skills-dir ` | Directory containing skill files (overrides default discovery) | — | | `--output-format ` | Output format: `text` (human-readable) or `json` (NDJSON event stream) | `text` | +| `--mode ` | `standalone` (default) or `server` — in server mode, routes through the Arc API's `/completions` endpoint | `standalone` | +| `--server-url ` | Arc API server URL (overrides `server.base_url` from `cli.toml`) | — | Permission levels control which tools are auto-approved: `read-only` allows read tools (`read_file`, `grep`, `glob`, `list_dir`) and subagent tools; `read-write` adds write tools (`write_file`, `edit_file`, `apply_patch`); `full` allows all tools including shell commands. Tools outside the permission level are either interactively prompted (if a TTY is present) or denied (with `--auto-approve`). See [default models by provider](/core-concepts/models#default-models).